一、类组件的写法
class B extends React.Component {
constructor(props) {
super(props);
}
render(){
return (
<div>hi</div>
)
}
}
export default B;
constructor 的参数是 new B(props) 用到的,super 的参数是父类构造函数用的,我们使用时用constructor接受props,然后用super把props传递个父类,父类挂靠到实例上(代替了我们自己挂靠上去)。
我们直接标签使用<B/>即可
二、props
初始化:super
读:this.props.xxx 即可读取
写:不要改写props,通知父元素去修改props
接受外部函数或数据
三、state
初始化:constructor里写this.state = {}
读:this.state.xxx
写:setState(()=>{})
四、生命周期钩子
- let div = document.createElement('div ) //这是div的create / construct过程
- div.textContent= 'hi' //这是初始化state
- document.body.appendChild(div) //这是div的mount过程
- div.textContent= 'hi2' //这是div的update过程
- div.remove() //这是div的unmount过程
一、constructor
就是类的构造函数
初始化props 初始化state,但此时不能调用setState,用来写bind this
constructor( ){
this.onClick = this.onClick.bind(this)
}可以用新语法代替
onClick = ( )=>{} 二、shouldComponentUpdate()
shouldComponentUpdate(nextProps, nextState)根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。默认行为是 state 每次发生变化组件都会重新渲染。大部分情况下,你应该遵循默认行为。
当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true。首次渲染或使用 forceUpdate() 时不会调用该方法。
可以将 this.props 与 nextProps 以及 this.state 与nextState 进行比较,并返回 false 以告知 React 可以跳过更新。请注意,返回 false 并不会阻止子组件在 state 更改时重新渲染。
shouldComponentUpate的用意:
因为种种原因,通过计算得出来的新state和旧state一样,那么就会执行render,两次虚拟dom比较,对比后发现没有变化,不更新UI。shouldCompontentUpdate目的就是为了跳过render函数调用。
其实React同样内置了这个函数:
React.PureComponent 与 React.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。
三、render
当 render 被调用时,它会检查 this.props 和 this.state 的变化并返回以下类型之一:
- React 元素。通常通过 JSX 创建。例如,
<div />会被 React 渲染为 DOM 节点,<MyComponent />会被 React 渲染为自定义组件,无论是<div />还是<MyComponent />均为 React 元素。只有一个根元素 - 数组或 fragments。 使得 render 方法可以返回多个元素。<React.Fragment></React.Fragment>render后会消失,只是占位用。可以用<></>代替
render() {return this.state.array.map(n= <span>key={n}>{n}</span> )
- Portals。可以渲染子节点到不同的 DOM 子树中。
- 字符串或数值类型。它们在 DOM 中会被渲染为文本节点
- 布尔类型或
null。什么都不渲染。(主要用于支持返回test && <Child />的模式,其中 test 为布尔类型。)
message = <div>xxx</div>
<>
{message}
</>render所有的循环都要有key
四、componentDidMount
componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。类似于Vue的mounted。获取一个div的宽度等等
你可以在 componentDidMount() 里直接调用 setState()。用户也不会看到中间状态。请谨慎使用该模式,因为它会导致性能问题。如果你的渲染依赖于 DOM 节点的大小或位置,比如实现 modals 和 tooltips 等情况下,你可以使用此方式处理
五、compontentDidUpate
componentDidUpdate(prevProps, prevState, snapshot)componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。
你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。
在此处进行网络请求,一般是有关更新数据的
六、compontentWillUnmount
componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。
remove和实例赋值为null都进行
这个钩子调用后该组件将永远不会重新渲染,若要重新渲染只能重新创建。
如果你在C.. DidMount里面监听了window scroll 那么你就要在c..WillUnmount里面取消监听
window.scroll = function(){} => window.scroll = null如果你在c..DidMount里面创建了Timer
那么你就要在c.WillUnmount里面取消Timer
在观看
如果你在c..DidMount里面创建了AJAX 请求
那么你就要在c.WillUnmount里面取消请求,AJAX请求没结束实例就死了
七、执行顺序
- constructor()-初始化
- shouldComponentUpdate()-渲染前首次渲染不会触发
- render()-渲染
- componentDidUpdate()-渲染后首次渲染不会触发
- componentDidMount()-挂载后立即
- compontentWillUnmount-销毁前
=====
首次渲染
- constructor()-初始化
- render()-渲染虚拟DOM
- UI更新-挂载DIFF
- componentDidMount()-挂载后立即
八、一些小东西
render阶段产生一个虚拟DOM,
appendChild阶段(mount)对比两个虚拟DOM更新视图
九、异步的setState
increment = () => {
this.setState({ val: this.state.val + 1 })
console.log(this.state.val) // 输出的是更新前的val --> 0
}不要指望在调用 setState 之后,this.state 会立即映射为新的值。要想得到新的值下面代码即可。
increment = () => {
this.setState(state=>{
val = state.val + 1
console.log(val)
return {val}
})
}对新值执行一些函数