一、setState
(一)异步性
setState是异步更新数据的:
以下代码执行结构中log打印出来的数据是1,表示setState是在log后被执行的,是一个异步操作
state = {
number: 1
}
add = () => {
this.setState({
number: this.state.number+1
})
console.log(this.state.number) // 1
}
这种异步性会导致如果一个方法中存在两个setState,后面的setState无法基于前面setState设置好的结果来进行相关操作,因此引出了推荐语法来解决这一问题:
(二)推荐语法
参数:
state:表示最新的state
props:表示最新的props
state = {
number: 1
}
add = () => {
this.setState((state, props) => {
return {
number: state.number+1
}
})
this.setState((state, props) => {
return {
number: state.number+1
}
})
console.log(this.state.number) // 1
}
1、log结果仍为1表示该方法也是异步的
2、使用这种方法执行过两次setState时,后面的setState通过回调函数中的参数state可以获取到最新的值,因此执行完毕number的值为3,也就是两次setState均有效。
(三)setState的回调函数
当需要在setState执行结束后进行一些操作时,可以调用setState方法提供的回调函数(参数形式):
state = {
number: 1
}
add = () => {
this.setState(
// 参数1:state
(state, props) => {
return {
number: state.number+1
}
},
// 参数2:callback
// 状态更新并重新渲染后立即执行
() => {
console.log('callback:', this.state.number) // 2
})
console.log(this.state.number) // 1
}
二、JSX
- JSX仅仅是createElement()方法的语法糖(简化语法)
- JSX语法被@babel/preset-react插件编译为createElement()方法
- React元素:是一个对象,用来描述你希望在屏幕上看到的内容
三、 组件性能优化
(一)减轻state
只存储跟组件渲染相关的数据,不用做渲染的数据不要放在state中,比如定时器id等,对于这种需要在多个方法中用到的数据,应该放在this中
(二)避免不必要的重新渲染
- 组件更新机制:父组件更新会引起子组件也被更新,但子组件没有任何变化时也会重新渲染,这就产生了不必要的渲染
- 解决方式:使用钩子函数shouldComponentUpadte(nextProps, nextState)
- 作用:通过返回值决定该组件是否重新渲染,返回true/false
- 触发时机:更新阶段的钩子函数,组件重新渲染前执行(shouldComponentUpadte→render)
// 钩子函数
shouldComponentUpdate(nextProps, nextState, nextContext) {
// 返回false,阻止组件重新渲染
// return false
// 最新的状态:
console.log('最新的state:', nextState)
// 更新前的状态:
console.log('this.state:', this.state)
return true
}
(三)纯组件
- 说明:纯组件内部的对比是shallow compare(浅层对比)
- 对于值类型来说:比较两个值是否相同(直接赋值即可,没有坑)
-
对于引用类型来说:只比较对象的引用(地址)是否相同
state或props中属性值为引用类型时,应该创建新数据,不要直接修改原数据
四、虚拟DOM和Diff算法
作用:实现部分更新(组件中如果只有一个DOM元素需要更新,不需要把整个组件内容重新进行渲染,因此需要使用该方法来实现部分元素的更新)
虚拟DOM:本质就是一个JS对象,用来描述我们希望在屏幕上看到的内容(UI)
执行过程
- 初次渲染时,React会根据初始state(Model),创建一个虚拟DOM对象(树)
- 根据虚拟DOM生成真正的DOM,渲染到页面中
- 当数据变化后(setState),重新根据新的数据,创建新的虚拟DOM对象(树)
- 与上一次得到的虚拟DOM对象,使用Diff算法对比(找不同),得到需要更新的内容
- 最终,React只将变化的内容更新(patch)到DOM中,重新渲染到页面
React路由