参看:视频地址

简单搭建一个react-cli:

2. React.createElement()

将object转化为 React语法

import React from 'react'
import ReactDOM from 'react-dom' /**
* React.createElement()
* 参数1: 标签名
* 参数2: 标签属性
* 参数3: 标签内容
* 参数4: 其他节点
*/
// 需要 babel loader 解析jsx语法
const myH1 = <div title='h1'>哈哈哈</div> const myDiv = React.createElement('div', { title: 'this is a div', id: 'mydiv' }, '这是一个div', myH1) // 将 myH1 放在 myDiv中,渲染到 #app 标签中
ReactDOM.render(myDiv, document.getElementById('app'))

React.createElement()

3. jsx 语法

3.1 jsx语法的配置

jsx语法不能直接使用,需要@babel/preset-react翻译。

// package.json
"devDependencies": {
"@babel/core": "^7.6.2",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/preset-env": "^7.6.2",
"@babel/preset-react": "^7.0.0",
"@babel/runtime": "^7.6.2",
"babel-loader": "^8.0.6",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.2"
},
"dependencies": {
"react": "^16.10.2",
"react-dom": "^16.10.2"
}
// .babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["@babel/transform-runtime", "@babel/plugin-proposal-class-properties"]
}
// webpack.config.js
const path = require('path')
const HtmlWebPackPlugin = require('html-webpack-plugin') const htmlPlugin = new HtmlWebPackPlugin({
template: path.join(__dirname, './src/index.html'),
filename: 'index.html'
}) module.exports = {
mode: 'development', // development production
plugins: [
htmlPlugin
],
module: {
rules: [
// 解析 jsx 语法
{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader"
},
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.json']
}
}

3.2 语法

  • 原生标签比如p、li、div如果要使用自定义属性,必须用data-前缀

  • 样式使用双大括号

import React, { Component } from "react"

export default class User extends Component {
render() {
const num = 100 // 数字
const str = "react 学习" // 字符串
const bool = true // 布尔值
const unde = undefined // undefined
const nu = null // null
const h4dom = <h4 style={{"width":"100px","height":20 + 30 + "px","backgroundColor" : "red"}}>这是一个h4标签</h4> // jsx 语法
// 遍历数组
const arrDom = [
<h5 key="1">这是一个h5标签1</h5>,
<h5 key="2">这是一个h5标签2</h5>,
<h5 key="3">这是一个h5标签3</h5>
]
// 字符串数组
const arr = ["白板", "幺鸡", "二条", "三饼"]
return (
<div>
{num + 1} - {str} - {bool.toString()} - {unde} - {nu}
<h3 title={str}>这是一个h3标签</h3>
{/* 数组会自动展开 */}
{h4dom}
{arrDom}
<hr />
{arr}
</div>
)
}
}

4. 创建组件

  • 组件名必须大写

  • 组件方法必须return

4.1 构造函数创建组件--无状态组件

import React, { Component } from "react"

// 将 person 传入 Stu 组件中 --- 子组件
// 使用 props 接收传进来的参数; props 只读,不可更改
function Stu(props) {
return (
<h1 style={{ color: "red", fontSize: 20 }}>
{/* 接受父组件传递过来的值 */}
Holle World: {props.name} - {props.age} - {props.gender}
</h1>
)
}

// 父组件
export default class User extends Component {
render() {
const person = {
name: "Danny",
age: 23,
gender: "boy"
}
return (
<div>
{/* 对象的解构赋值来传递数据 */}
<Stu {...person}></Stu>
</div>
)
}
}

4.2 class关键字创建组件---有状态组件

import React, { Component } from "react"

// 将 person 传入 Stu 组件中 --- 子组件
// 使用 props 接收传进来的参数; props 只读,不可更改
class Stu extends React.Component{
// render函数 是渲染当前组件对应的虚拟dom元素, props 接收 父组件 传递过来的值
render(props){
// 通过 this.props.*** 就可以接收数据
//返回一个jsx语法
return <h1 style={{color: '#1da57a'}}>Holle World { this.props.name } - { this.props.age} - { this.props.gender }</h1>
}
} export default class User extends Component {
render() {
const person = {
name: "Danny",
age: 23,
gender: "boy"
}
return (
<div>
{/* 对象的解构赋值来传递数据 */}
<Stu {...person}></Stu>
</div>
)
}
}

用构造函数创建出来的组件,和用class创建出来的组件,

这两种不同的组件之间的本质区别就是:有无state属性 和 生命周期函数!

有状态组件和无状态组件之间的本质区别就是:有无state属性!

5. react的样式

5.1 渲染评论列表样式

  • 行内样式

  • css样式写成js对象的形式

import React, { Component } from "react"

// 这是评论列表组件
export default class CommentList extends Component {
constructor(params) {
super()
this.state = {
CommentList: [
{ id: 1, user: '张三', content: '哈哈,沙发' },
{ id: 2, user: '张三2', content: '哈哈,板凳' },
{ id: 3, user: '张三3', content: '哈哈,凉席' },
{ id: 4, user: '张三4', content: '哈哈,砖头' },
{ id: 5, user: '张三5', content: '哈哈,楼下山炮' }
]
}
}
render(props){
return (
<div>
{ /* 头部的行内样式 */}
<h1 style={{ color: 'red', fontSize: '24px', backgroundColor: 'yellow', fontWeight: 700 }}>这是评论列表组件</h1>
{ this.state.CommentList.map(item => <CommentDetail key={ item.id } { ...item }></CommentDetail> )}
</div>
)
}
} // 定义子组件的object样式
const styles = {
itemStyle: { border: '1px dashed #ddd', margin: '10px', padding: '10px', boxShadow: '0 0 10px #ddd' },
userStyle: { fontSize: '14px' },
contentStyle: { fontSize: '12px' }
} // 子组件
function CommentDetail(props) {
console.log(props)
return (
<div style={ styles.itemStyle }>
<h1 style={ styles.userStyle }>评论人:{ props.user }</h1>
<p style={ styles.contentStyle }>评论内容:{ props.content }</p>
</div>
)
}

使用sass

第三方使用css;自己的样式使用sass

配置loader

{
test: /\.css$/,
use: [ 'style-loader', 'css-loader']
},
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[path][name]-[local]-[hash:base64:5]',
},
}
},
{ loader: 'sass-loader' }
]
}

使用:

// .jsx 文件
// 自己的 sass 文件,需要使用 sass 配置规则解析
import cssobj from '@/css/commentList.scss'
console.log('commentList.css', cssobj) import 'bootstrap/dist/css/bootstrap.css' class CommentList extends React.Component {
constructor(params) {
super()
}
render(props){
return (
<div>
{/* 自己的 css */}
<h1 className={ [cssobj.title, 'test'].join(' ') }>这是评论列表组件</h1>.
{/* 第三方的 css */}
<button className="btn btn-primary">按钮</button>
</div>
)
}
}

6. react中的事件

模拟实现 VUE 中的双向绑定数据原理

//#region 介绍 react 中绑定事件的标准格式
import React from "react" class BindEvent extends React.Component {
constructor(params) {
super()
this.state = {
msg: '哈哈',
name: 'LiMing',
color: '#' + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, '0')
}
}
render(props){
return (
<div>
<h1>BindEvent 组件</h1>
{/* 绑定点击事件 onClick */}
<button onClick={ () => this.myclickHandler(this.state.color) }>按钮</button>
{/* 显示 state 中的数据 */}
<h3>{ this.state.msg }</h3>
{/* 模拟实现 VUE 中的双向绑定数据原理 */}
<input type="text" ref="txt" style={{ width: '100%'}} value={ this.state.msg } onChange={e => this.txtChange(e) }/>
</div>
)
}
txtChange = (e) => {
// 获取 input 中 value 的两种方法
// console.log(e.target.value === this.refs.txt.value) // true
this.setState({
msg: e.target.value // this.refs.txt.value
})
}
myclickHandler = color => {
// this.setState({}, callbcak) 是异步的,需要在 callbcak 获取最新的值
this.setState({
msg: color
},() => {
console.log( '2', this.state.msg )
})
// 还是未修改的值
console.log( '1', this.state.msg )
}
} export default BindEvent

7. react组件的生命周期函数

componentWillMount:组件将要被挂载,此时还没有开始渲染虚拟DOM
render:第一次开始渲染真正的虚拟DOM,当render执行完,内存中就有了完整的虚拟DOM了
componentDidMount:组件完成挂载,此时,组件已经渲染到页面上了,数据和页面达到同步,当这个方法执行完,组件进入 运行中 的状态
    • 组件运行阶段
componentWillReceivrProps:组件将要接受新的属性,此时,只要这个方法被触发,就证明父组件为当前子组件传递了新的属性值
shouldComponenUpdate:组件是否需要被更新,此时,组件尚未开始更新,但是 state 和 props 中的数据是最新的
componentWillUpdate:组件将要被更新,此时尚未开始更新,内存中的虚拟DOM树还是旧的
render:此时,重新根据最新的 state 和 props 重新渲染一颗存在内存中的 虚拟DOM树,当 render 调用完毕,内存中旧的DOM树 替换 成新的 DOM树了,但是页面还是旧的
componentDidUpdate:此时,页面又被重新渲染了,state 和 虚拟DOM 页面都是最新的,并且保持同步
    • 组件销毁阶段
componentDidUpdate:组件将要被卸载,此时组件还可以正常使用

使用计数器学习react的生命周期:

import React from "react"
import ReactTypes from 'prop-types' class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: 'ok',
count: props.initcount
}
} // 父组件没有传递值是,设置默认值
static defaultProps = {
initcount: 0
} // 创建静态的 propTypes 对象,可以校验 父组件传递过来的值得类型
static propTypes = {
initcount: ReactTypes.number // prop-types 指定数据类型
} // 组件将要被挂载到页面上,此时,数据已经存在,但是还没有开始渲染虚拟DOM = VUE: created
componentWillMount() {
console.log('componentWillMount 函数')
// 无法获取DOM,页面 和 虚拟DOM 还没有渲染
console.log(document.querySelector('.myh3')) // null
// props 和 state 可以获取到
console.log(this.props.initcount) //
console.log(this.state.msg) // ok
this.myselfFunc()
} // 渲染内存中的虚拟DOM,但是页面尚未真正显示DOM元素
render() {
// 每当调用 render 函数时,页面上的元素还是旧的
console.log('render 函数')
// return 之前,虚拟DOM还没有创建, return 之后,虚拟DOM创建,但是还没有挂载到页面上
return (
<div>
<h1>这是计数器组件</h1>
<input id="btn" type="button" value="+1" onClick={this.increment} />
<hr/>
<h3 ref="h3" className="myh3">当前数量为:{ this.state.count }</h3>
<h3 className="myh3">当前数量为:{ this.props.initcount }</h3>
</div>
)
} // 组件挂载到页面上,会进入这个生命周期函数,此时页面上渲染虚拟DOM了 == VUE mounted
componentDidMount() {
console.log('componentDidMount 函数')
console.log(document.querySelector('.myh3')) // <h3 ... </h3>
// 使用原生js方法,改变 count 值
// document.querySelector('#btn').onclick = () => {
// this.setState({
// count: this.state.count + 2
// })
// }
} // 从这里判断组件是否需要更新
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate 函数')
// 该周期中必须返回一个 boolean 值
// 返回 false,则不执行其他生命周期函数,但是 state 的数据会被更改
// 返回 true,继续执行其他生命周期函数
// console.log(this.state.count) // 此时直接使用this.state是未更改的值
// console.log(nextProps, nextState) // 最新的 props 和 state
// return nextState.count % 2 === 0? true: false
return true
} // 组件将要更新,此时尚未更新,在进入这个生命周期函数的时候,内存中的虚拟DOM是旧的,页面上的DOM元素也是旧的
componentWillUpdate() {
console.log('componentWillUpdate 函数')
console.log(document.querySelector('.myh3').innerText) // 旧的数据
console.log(this.refs.h3.innerText)
} // 此时虚拟DOM,页面,数据都是最新的
componentDidUpdate() {
console.log('componentDidUpdate 函数')
console.log(this.refs.h3.innerText)
}
myselfFunc() {
console.log('自己定义的函数');
} increment = () => {
this.setState({
count: this.state.count + 1
})
}
} export default Counter

使用父子组件学习componentWillReceiveProps周期函数

  • 注意:第一次渲染子组件时,componentWillReceiveProps不会传递props属性。

import React from "react"

class Parent extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: '父组件中的 msg 消息'
}
}
render() {
return (<div>
<h1>这是父组件</h1>
<input type="button" value="点击修改msg的值" onClick={this.changeMsg}/>
<hr/>
<Son pmsg={ this.state.msg }></Son>
</div>)
} changeMsg = () => {
this.setState({
msg: '更改了,变成新值了'
})
}
} class Son extends React.Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (<div>
<h3>这是子组件</h3>
<p>{ this.props.pmsg }</p>
</div>)
} // 组件接受外界传值触发
// 子组件第一次被渲染到页面上时候,不会触发这个方法,第二次以后才会触发
componentWillReceiveProps(nextProps) {
console.log('被触发了')
// 注意:在 componentWillReceiveProps 中拿到的值是未更改的值!!
// console.log(this.props.pmsg)
console.log(this.props.pmsg + '----' + nextProps.pmsg);
}
} export default Parent

8. react中绑定this传递参数的3中方式

import React from "react"

class BindThis extends React.Component {
constructor(props) {
super(props)
this.state = {
msg: '这是 BindThis组件中的 msg 消息'
} // 绑定 this 并传参的方式 ②
// bind 的返回值 是调用函数和参数的 copy
// 注意:bind 不会修改原函数的 this 指向
this.changeMsg2Copy = this.changeMsg2.bind(this, '参数one', '参数two')
}
render() {
return (<div>
<h1>这是 BindThis 组件 </h1>
{/* 方式 ① */}
{/* bind 修改函数内部的 this 指向,指向 bind 参数列表中的第一个参数 */}
<input type="button" value="react 中绑定 this 传递参数的3中方式1" onClick={ this.changeMsg1.bind(this, '参数1', '参数2')}/>
<hr />
{/* 方式 ② */}
<input type="button" value="react 中绑定 this 传递参数的3中方式2" onClick={ this.changeMsg2Copy }/>
<hr />
{/* 方式 ③ */}
<input type="button" value="react 中绑定 this 传递参数的3中方式3" onClick={ () => this.changeMsg3('参数1111', '参数2222') }/> <h2>{ this.state.msg }</h2>
</div>)
} changeMsg1(arg1, arg2) {
console.log(this) // 指向实例
this.setState({
msg: '变成新值了' + arg1 + arg2
})
} changeMsg2(arg1, arg2) {
console.log(this) // undefined
this.setState({
msg: '变成新值了' + arg1 + arg2
})
} changeMsg3 = (arg1, arg2) => {
console.log(this) // 指向实例
this.setState({
msg: '变成新值了' + arg1 + arg2
})
}
} export default BindThis

9. context多重组件传值

import React from "react"
import ReactTypes from "prop-types"
class Conm1 extends React.Component {
constructor(params) {
super()
this.state = {
color: "red"
}
} // 1. 在父组件定义 func,这个func固定的名字 getChildContext
// 内部必须返回一个对象,这个对象就是要共给子孙组件的数据
getChildContext() {
return {
color: this.state.color
}
} // 2. 使用 属性校验,规定一下传递给子组件的数据类型,固定名字 childContextTypes
static childContextTypes = {
color: ReactTypes.string // 规定传递给子组件的数据类型
}
render(props) {
return (
<div>
<h1>这是父组件:通过 getChildContext 将父组件中的颜色 red 传递给孙子组件</h1>
<hr />
<Conm2></Conm2> </div>
)
}
} class Conm2 extends React.Component {
render(props) {
return (
<div>
<h3>这是子组件</h3>
<hr />
<Conm3></Conm3>
</div>
)
}
} class Conm3 extends React.Component {
constructor(params) {
super()
this.state = {}
}
// 3. 先来个属性校验,校验父组件传递过来的参数类型
static contextTypes = {
color: ReactTypes.string // 这里,子组件一定要校验一下父组件传递过来的 context 的数据类型
}
render(props) {
return (
<div>
<h5 style={{ color: this.context.color }}>
这是孙子组件 --- {this.context.color}
</h5>
</div>
)
}
}
export default Conm1

React 学习笔记(1) 基础语法和生命周期的更多相关文章

  1. Java学习笔记之---基础语法

    Java学习笔记之---基础语法 一. Java中的命名规范 (一)包名 由多个单词组成时,所有字母小写(例如:onetwo) (二)类名和接口 由多个单词组成时,所有单词首字母大写(例如:OneTw ...

  2. React学习笔记(五)State&声明周期

    React学习笔记(五) 四.State&声明周期 可以为组件添加"状态(state)".状态与属性相似,但是状态是私有的,完全受控于当前组件. 局部状态就是只能用于类(定 ...

  3. React学习笔记(一) 基础知识

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我. React的基 ...

  4. React 入门学习笔记整理(七)—— 生命周期

    (1)react 生命周期 只有类组件有生命周期,函数组件没有生命周期 1.挂载阶段:这些方法会在组件实例被创建和插入DOM中时被调用: 1)constructor(props) 初始化组件的状态.绑 ...

  5. Hive学习笔记:基础语法

    Hive基础语法 1.创建表 – 用户表 CREATE [EXTERNAL外部表] TABLE [IF NOT EXISTS 是否存在] HUserInfo ( userid int comment ...

  6. Java学习笔记之基础语法(顺序,条件,循环语句)

    顺序结构:自上而下 条件分支选择结构: if条件语句   1,一旦某一个分支确定执行以后,其他分支就不会执行.if后面的条件必须是boolean类型   2,if  后面如果不加大括号,默认相邻的下一 ...

  7. iOS学习笔记(四)——iOS应用程序生命周期

    开发应用程序都要了解其生命周期,开始接触android时也是从应用程序生命周期开始的,android的应用程序生命周期更多是其组件的生命周期,例如Activity.Service.今天我们接触一下iO ...

  8. react学习(6)——关于组件生命周期的问题

    在项目开发的过程中,遇到了一个问题: 父组件请求后台数据,收到后将数据以props传给子组件,子组件根据收到数据的不同,显示不同的内容,同时,子组件自身可以根据click操作改变根据父组件的数据显示的 ...

  9. maven权威指南学习笔记(四)—— maven生命周期(lifecycle)

    定义: 生命周期是包含在一个项目构建中的一系列有序的阶段 举个例子来说就是maven 对一个工程进行: 验证(validate) -- 编译源码(compile) -- 编译测试源码(test-com ...

随机推荐

  1. iOS直播集成和问题总结(阿里云直播)

    https://www.jianshu.com/p/714ce954e628 最近接手公司的直播项目,对以前遗留的问题做处理和优化, 于是顺便看了下阿里云直播的文档,在下面写下对直播的理解和遇到的问题 ...

  2. SCP 上传

    https://www.runoob.com/linux/linux-comm-scp.html scp 当前路径(绝对路径) root@xx.xx.xx :/xx/xx/xx/

  3. C#往TextBox的方法AppendText加入的内容里插入换行符----转载

    C# TextBox换行[huan hang]时你往往会想到直接付给一个含有换行[huan hang]符"\n"的字符[zi fu]串[zi fu chuan]给Text属性[sh ...

  4. Java Hashtable遍历与方法使用

    参考文档 我参考了Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例,阅读了jdk 1.8的源码 Hashtable的继承关系 Hashtable继承了Dictionary类, ...

  5. DatePicker和DataPickerDialog以及AutoCompleteTextView的基本使用方法

    1.DatePicker和DatePickerDialog的基本使用方法: main.xml: <?xml version="1.0" encoding="utf- ...

  6. JQuery--jQuery对象与DOM对象

    1.JQuery是继Prototype之后又一个优秀的JavaScript库: 2.Jquery的理念是“写得少,做得多”,它有如下优势: --1)轻量级:2)强大的选择器:3)出色的DOM操作的封装 ...

  7. NSArary自定义对象排序 NSComparator, compare

    reference from :http://mobile.51cto.com/hot-434804.htm 1.构建Person类 Person.h @interface Person : NSOb ...

  8. C# webkit 内核浏览器 访问https 网站 提示 Problem with the SSL CA cert (path? access rights?)

    C# webkit 内核浏览器 访问https 网站 提示 Problem with the SSL CA cert (path? access rights?) 解决方法: 陈凯文11112014- ...

  9. SciPy 信号处理

    章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...

  10. Ubuntu 19.10将使用GCC 9作为默认编译器

    作为我们这一周期一直期待的变化,Ubuntu 19.10升级到GCC 9作为GCC 8的默认系统编译器. Ubuntu 19.10(和Ubuntu 20.04 LTS)将使用GCC 9 stable作 ...