React v16.4.0
一、理解优点
1、虚拟DOM
2、合成事件(SyntheticEvent)
1、虚拟DOM
在React中,render执行的结果得到的并不是真正的DOM节点,而仅仅是JavaScript对象,称之为虚拟DOM。
虚拟DOM是在DOM的基础上建立了一个抽象层,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到DOM中。
虚拟DOM的原理:
React会在内存中维护一个虚拟DOM树,对这个树进行读或写,实际上是对虚拟DOM进行。当数据变化时,React会自动更新虚拟DOM,然后将新的虚拟DOM和旧的虚拟DOM进行对比,找到变更的部分,得出一个diff,然后将diff放到一个队列里,最终批量更新这些diff到DOM中。
虚拟DOM的优点:
最终表现在DOM上的修改只是变更的部分,可以保证非常高效的渲染。
虚拟DOM的缺点:
首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。
2、合成事件(SyntheticEvent)
因为在浏览器中直接操作DOM会占用很大的内存,并且绑定浏览器事件也会占用一定的内存(绑定事件越多,占用内存越大)。所以,React实现了一套合成系统,简化了事件逻辑,同时解决了浏览器(FF浏览器和IE浏览器)的兼容问题
基本原理是
在JSX上面声明的所有事件,都会别委托在最外层的document节点上(事件委托),并且根据事件的名和组件名存储回调函数(listenerBank),当某个组件触发事件是,在在document节点上绑定的监听函数(dispatchEvent),就会找到这个组件和它的所有父组件(ancestors),对每个组件创建对应React合成事件(SyntheticEvent)并批处理(runEventQueueInBatch(events)),从而根据事件名和组件名调用(invokeGuardedCallback)回调函数。
但是
由于React合成事件系统模拟事件冒泡的方法是构建一个自己及父组件队列,因此也带来一个问题,合成事件不能阻止原生事件,原生事件可以阻止合成事件。用 event.stopPropagation() 并不能停止事件传播,应该使用 event.preventDefault()。
二、组件的生命周期
为了更好地理解React组件的生命周期,编写了如下代码
//Father.js
import React from 'react'
import Child from './Child.js'
export default class Father extends React.Component{
constructor(){
super()
this.state={
randomData:0,
hasChild:true
}
console.log('father constructor')
}
componentWillMount(){
console.log('father componentWillMount')
}
componentDidMount(){
console.log('father componentDidMount')
}
componentWillReceiveProps(nextProps){
console.log('father componentReceiveProps')
}
shouldComponentUpdate(nextProps,nextState){
console.log('father shouldComponentUpdate nextProps:'
+JSON.stringify(nextProps)
+'------nextState:'
+JSON.stringify(nextState))
return true
}
componentWillUpdate(){
console.log('father componentWillUpdate')
}
componentDidUpdate(){
console.log('father componentDidUpdate')
}
componentWillUnmount(){
console.log('father componentWillUnmount')
}
handleChangeState(){
this.setState({
randomData:Math.floor(Math.random()*100)
})
}
handleChangeChild(){
this.setState({
hasChild:!this.state.hasChild
})
}
render(){
console.log('father render')
return (
<div>
<h1>Father State ---{this.state.randomData}</h1>
<button onClick={this.handleChangeState.bind(this)}>Change</button>
<p><button onClick={this.handleChangeChild.bind(this)}>{this.state.hasChild?'hide':'show'}</button></p>
{this.state.hasChild?( <Child data={this.state.randomData} />):''}
</div>
)
}
}
//Child.js
import React from 'react'
export default class Child extends React.Component{
constructor(){
super()
console.log('child constructor')
}
componentWillMount(){
console.log('child componentWillMount')
}
componentDidMount(){
console.log('child componentDidMount')
}
componentWillReceiveProps(nextProps){
console.log('child componentReceiveProps')
}
shouldComponentUpdate(nextProps,nextState){
console.log('child shouldComponentUpdate nextProps:'
+JSON.stringify(nextProps)
+'------nextState:'
+JSON.stringify(nextState))
return true
}
componentWillUpdate(){
console.log('child componentWillUpdate')
}
componentDidUpdate(){
console.log('child componentDidUpdate')
}
componentWillUnmount(){
console.log('child componentWillUnmount')
}
render(){
console.log('child render')
return (<h2>child recive props---{this.props.data}</h2>)
}
}
运行结果如下
image.png
控制台输出的内容如下
father constructor
father componentWillMount
father render
child constructor
child componentWillMount
child render
child componentDidMount
father componentDidMount
点击Change按钮,
页面变化如下
image.png
控制台输入结果如下
father shouldComponentUpdate nextProps:{}------nextState:{"randomData":18,"hasChild":true}
father componentWillUpdate
father render
child componentReceiveProps
child shouldComponentUpdate nextProps:{"data":18}------nextState:null
child componentWillUpdate
child render
child componentDidUpdate
father componentDidUpdate
点击hide按钮,
页面变化如下
image.png
控制台输入结果如下
father shouldComponentUpdate nextProps:{}------nextState:{"randomData":18,"hasChild":false}
father componentWillUpdate
father render
child componentWillUnmount
father componentDidUpdate
点击show按钮,
页面变化如下
image.png
控制台输入结果如下
father shouldComponentUpdate nextProps:{}------nextState:{"randomData":18,"hasChild":true}
father componentWillUpdate
father render
child constructor
child componentWillMount
child render
child componentDidMount
father componentDidUpdate
由控制台输出的内容顺序可以理解到React组件各个生命周期钩子函数的执行顺序
下图可以更好地理解组件的生命周期
React生命周期.png
网友评论