一、函数组件
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
使用方法:<Welcome name="frank"/>
如何添加 props(外部数据)?
直接读取参数 props.xxx
如何添加 state(内部数据) ?
用 useState 返回数组,第一项读,第二项写
注意:通过 setX(新值)来更新 UI,跟类组件不同,没有 this,一律使用参数和变量
setX 完全不会合并属性,可使用 ...操作符来解决
二、类组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}
使用方法:<Welcome name="frank"/>
如何添加 props(外部数据)?
直接读取属性 this.props.xxx
如何添加 state(内部数据) ?
用 this.state 读,this.setState 写
注意:setState 会异步更新 UI ,setState 之后,state 不会马上改变,立马读 state 会失败,推荐使用setState(函数),尽量不要修改旧 state(不可变数据)
setState 会自动合并第一层属性,但不会合并第二层,可以使用 Object.assign 或者 ...操作符来解决
三、ES6 创建类组件
import React from 'react';
class B extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>hi</div>
)
}
}
export default B;
props(外部数据)初始化:
class B extends React.Component {
constructor(props) {
super(props);
}
render(){}
}
要么不初始化,即不写 constructor,要初始化必须写全套(不写 super 直接报错)
这样做后,this.props 就是外部数据对象的地址了
读取外部数据
render(){
return <div onClick={this.props.onClick}>
{this.props.name}
<div>
{this.props.children}
</div>
</div>
}
// 通过 this.props.xxx 读取
props 的作用
接受外部数据,只能读不能写,外部数据由父组件传递
接受外部函数,在恰当的时机调用该函数,该函数一般是父组件的函数
state(内部数据)初始化:
constructor(props) {
super(props);
this.state = {
user: {name:'frank', age:18}
}
}
render() { /* ... */ }
}
读用this.state
this.state.xxx.yyy.zzz
写用 this.setState(???, fn)
this.setState(newState, fn)
setState 不会立刻改变 this.state,会在当前代码运行完后,再去更新 this.state,从而触发UI更新
this.setState((state, props) =>newState, fn) 这种方式的 state 更易于理解
fn 会在写入成功后执行
写时会 shallow merge
setState 会自动将新 state 与旧 state 进行一级合并
四、生命周期
constructor() 在这里初始化 state
用途:
初始化 props
初始化 state,但此时不能调用 setState
用来写bind this
shouldComponentUpdate() return false 阻止更新
用途:
返回true表示不阻止 UI 更新
返回false表示阻止UI更新
它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活地设置返回值,以避免不必要的更新
render() 创建虚拟 DOM
用途:
展示视图
return (<div>...</div>)
只能有一个根元素
如果有两个根元素,就要用 <React.Fragment> 包起
<React.Fragment/>可以缩写成<></>
componentDidMount() 组件已出现在页面
用途:
在元素插入页面后执行代码,这些代码依赖 DOM
此处可以发起加载数据的 AJAX 请求(官方推荐)
首次渲染会执行此钩子
componentDidUpdate() 组件已更新
用途:
在视图更新后执行代码
此处也可以发起AJAX请求,用于更新数据
首次渲染不会执行此钩子
在此处setState可能会引起无限循环,除非放在 if 里
若 shouldCom...Update 返回false,则不触发此钩子
componentWillUnmount() 组件将死
用途:
组件将要被移出页面然后被销毁时执行代码
unmount 过的组件不会再次 mount
五、创建函数组件
const Hello = (props) => {
return <div>{props.message}</div>
}
const Hello = props => <div>{props.message}</div>
function Hello(props){
return <div>{props.message}</div>
}
函数组件代替 class 组件
问题1:函数组件没有 state
解决方法:React v16.8.0推出 Hooks API,其中的一个叫做 useState 的 API 可以解决问题
问题2:函数组件没有生命周期
解决方法:Hooks API 中有个 useEffect 的 API 可以解决问题
useEffect 模拟生命周期
模拟 componentDidMount()
useEffect(()=>{ console.log('第一次渲染') },[])
模拟 componentDidUpdate()
useEffect(()=>{ console.log('任意属性变更')}) useEffect(()=>{ console.log('n变了')}, [n])
模拟 componentWillUnmount()
useEffect(()=>{ console.log('第一次渲染') return ()=>{ console.log('组件要死了') } })
其他生命周期的模拟
模拟 constructor()
函数组件执行的时候,就相当于 constructor
模拟 shouldComponentUpdate()
React.memo 和 useMemo 可以解决
模拟 render()
函数组件的返回值就是 render 的返回值
*本文为鲲游北冥的原创文章,著作权归本人和饥人谷所有,转载务必注明来源