学习目标
- 能够知道 setState() 更新数据时异步的
- 能够知道 JSX 语法的转化过程
- 能够说出React组件的更新机制
- 能够对组件进行性能优化
- 能够说出虚拟DOM和Diff算法
一、更新数据
1、更新数据时异步的
setState() 更新数据时异步的
注意:使用该语法时,后面的setState() 不能依赖上一个
可以多次调用setState(), 只会触发一次重新渲染
class App extends React.Component {
state = {
count: 1
}
handleclick = () => {
this.setState({
count: this.state.count + 1
})
console.log('count',this.state.count) // 1
// 页面显示的是2
}
render() {
return (
<div>
<h1>计数器:{this.state.count}</h1>
<button onClick={this.handleClick}> +1 </button>
</div>
)
}
}
2、解决方式 (推荐方式)
第一个参数
State: 表示最新的state
props:表示最新的props
state = {
count: 1
}
this.setState((state,props) => {
return {
count: state.count + 1
}
})
this.setState((state,props) => {
console.log(state,'2') //2
return {
count: state.count + 1
}
})
第二个参数
是个回调函数
this.setState((state,props) => {
return {
count: state.count + 1
}
},() => {
console.log('状态更新完成之后立即执行',this.state)
})
二、JSX 语法的转化过程
- JSX 仅仅是 createElement() 方法的语法糖 ( 简化语法 )
- JSX 语法被 @babel/preset-react 插件编译为 createElement() 方法
- React 元素:是一个对象,用来描述你希望在屏幕上看到的内容
| JSX语法 | createElement() | React元素 |
|---|---|---|
// JSX 语法
const element = (
<h1 className="greeting">
Hello JSX;
</h1>
)
// createElement()
const element = React.createElement(
'h1',
{className:"greeting",
"Hello JSX"
}
)
// React 元素
const element = {
type:"h1",
props: {
className: 'greeting',
children: 'Hello JSX'
}
}
三、组件更新机制
- setState() 两个作用:1.修改state 2.更新组件(UI)
- 过程:父组件重新渲染时,也会重新渲染子组件,但只会渲染当前组件子树(当前组件及其所有子组件)
例如

四、组件性能优化
1、减轻state
- 减轻state:只存储跟组件渲染相关的数据(比如:count / 列表数据 / loading 等)
- 注意:不用渲染的数据不要放在state中,比如定时器 id等
- 对于需要多个方法共享又和渲染没有关系,应该放在this中
class Hello extends Component {
timerId = null;
componentDidMount() {
this.timerId = setInterVal(() => {},2000)
}
componentWillUnmount() {
clearInterval(this.TimerId)
}
render() { …… }
}
2、避免不必要的重新渲染
- 组件更新机制:父组件更新子组件也跟着更新
- 问题:造成子组件没变化也会更新
- 解决方式:使用狗子函数should ComponentUpdate(nextProps,nextState)
- 作用:返回值决定是否更新true更新,false不更新
- 触发时机:shouldComponentUpdate ---> render
class Hello extends React.Component {
shouldComponentUpdate(nextProps,nextState) {
console.log("最新状态:",nextState,"当前状态:",this.state)
console.log("最新props:",nextProps,"当前props:",this.props)
// 与当前的值不一样就更新
return nextState.number !== this.state.number
}
render () {……}
}
3、纯组件
- 纯组件:PureComponent 与 React.Component功能相似
- 区别:PureComponent内部自动实现了shouldComponentUpdate
- 原理:纯组件内部通过分别对比前后俩次props和state的值,来决定重新渲染组件
class Hello extends React.PureComponent {
render() {
return (
<div>纯组件</div>
)
}
}
1、比较原理
纯组件内部的对比上shallow compare(浅层比较)
引用类型来说:只比较对象的引用是否相同
基本类型:比较值是否相同 没有问题
// 对象
const newObj = {...state.obj,number:2}
setState({obj:newObj})
// 数组也是
// 不能用数组的push/unshift直接修改
// 应该用concat或者slice 返回新数组的方法
this.setState({
list: [...this.state.list,新数据]
})
五、虚拟DOM和Diff算法
render方法调用并不意味着浏览器中的重新渲染!!!!
render方法调用仅仅说明要进行diff
1、虚拟DOM
:本质上就是JS对象,用来描述你希望在屏幕上看到的内容
/* 虚拟DOM对象 */
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello JSX!'
}
}
/* HTML结构 */
<h1 class="greeting">Hello JSX!</h1>
3、Diff算法
执行过程
- 初次渲染时,React会根据初试state(Model) ,创建一个虚拟DOM对象
- 根据虚拟DOM生成真正的DOM,渲染到页面中
- 当数据变化后(setState()), 重新根据新的数据,创建新的虚拟DON对象
- 与上一次得到的虚拟DOM树,使用Diff算法对比,得到需要更新的内容
- 最终,React只将变化的内容更新到DOM中,重新渲染