上节课我们讨论了一下生命周期中组件更新时的流程,但是当时流程图中那一块总共有 3 个入口,目前我们才只说了第一个我们最熟悉的也是最简单的。这节课呢我们就来讨论介绍一下稍微要陌生一点的forceUpdate
。
回顾
在进入这节课的课程之前呢我们先来对上节课的内容来做一个简单的回顾。
- 组件完成挂载并执行完了
componentDidMount
之后按顺序执行了 4 个生命周期钩子 - 通过
shouldComponentUpdate
方法判断是否允许更新 - 通过
componentWillUpdate
方法做更新前的准备工作 - 通过
render
方法更新组件 - 更新组件之后立即调用
componentDidUpdate
方法 shouldComponentUpdate
必须返回bool
类型- 如果没有写
shouldComponentUpdate
方法,react
会自动补齐该方法,并且默认该方法返回true
以上便是我们上节课的主要知识点,那么接下来我们开始我们这节课的学习。
forceUpdate
方法
我们上节课可以看得出来,我如果想要走setState
这一个流程那么是不是就一定要在组件的某个地方调用setState
方法,那么同理,我们要是想要走forceUpdate
流程的话也一样要在组件中调用forceUpdate
方法。
但是呢,大家是不是觉得我们之前都没用见过这个forceUpdate
方法,这个方法到底是个啥啊?我这个方法名是不是可以拆成两个英文单词来看?force
和update
?大家有人要说,这个update
我们都知道,就是更新的意思。可是这个force
是啥啊?
force
这个词呢其实有强制的意思,那么连到一起是什么?forceUpdate
就是强制更新。什么叫强制更新呢?我们之前那个setState
流程叫正常更新,我们从最一开始学state
的时候就说了嘛,我们react
的设计哲学就是通过改变state
来驱动页面更新。那么这种方法无非就是react
中组件更新的一个标准方法,那么这肯定就是正常更新啊。
那么正常更新是什么流程?先更改state
然后去询问是否允许组件更新,如果允许,再更新,否则就不更新。那么强制更新呢?肯定就是根本不会去问你允不允许更新,我不管你允不允许,我就要更新。字面上是不是就可以这么理解?
但是我们在回过头来想,我们正常更新的前提是什么?是不是我通过setState
修改了state
的值,然后触发了这一整套流程?但是如果有些时候我不想去修改state
,但是我就是要更新页面,那么我们怎么办?所以react
就提供了forceUpdtae
方法。这就是forceUpdate
方法和setState
方法的本质上的区别。
强制更新流程
流程图
执行流程
我们从流程图上面来看的话,是不是觉得也不难啊?强制更新也就是比正常更新少了一个调用shouldComponentUpdate
方法的环节。
这个当然也好理解,上节课我们说了,shouldComponentUpdate
方法是个什么啊?是不是一个阀门?阀门开启才能往下走到更新流程,但是我们现在要用强制更新了,那么这么可能还会受这个阀门的影响呢?
但是forceUpdate
到底都是在什么应用场景下才会用到呢?其实没有很多应用场景的,只有当我们不想更改state
的时候但是又想让组件更新的时候才会用。那么我们来测试一下这个流程呗,这个流程我们就不再赘述了啊,就是直接调用forceUpdate
触发强制更新流程,然后调用componentWillUpdate
方法来做准备工作,紧接着通过render
方法来更新组件,待到组件更新完毕立即调用componentDidUpdate
方法。
class Count extends React.Component { state = { count: 0 }; componentWillUpdate() {console.log("Count-componentWillUpdate");} componentDidUpdate() {console.log("Count-componentDidUpdate");} render() { console.log("Count-render"); const { count } = this.state; return ( <div> <h2>当前点击 {count} 次</h2> <button onClick={this.add}>Add</button> <button onClick={this.unmount}>Unmount</button> <button onClick={this.force}>Force</button> </div> ); } add = () => { this.setState({ count: this.state.count + 1 }); }; unmount = () => { ReactDOM.unmountComponentAtNode(document.getElementById("test")); }; force = () => { this.forceUpdate(); } }
我们来看一下代码,我们依然还是之前的案例,但是因为我们是强制更新,那么shouldComponentUpdate
方法就不需要了,然后我们添加了一个新的按钮叫Force
,那么我们说了之前要是想要触发正常更新的流程是不是要调用setState
?那么强制更新也一样,我们得调用forceUpdate
方法来触发这个流程。那么我们就给Force
按钮添加了onClick
回调,并在这个回调里面来调用forceUpdate
。
那么我们怎么知道这个forceUpdate
到底有没有被调用呢?如果我们调用了的话是不是就一定会调用componentWillUpdate
方法,render
方法以及componentDidUpdate
方法啊?那么我们来看一下效果:
控制台中打印出了相关方法的调用情况,那么我们再看一下state
我们看见state
依然还是 0 ,没有发生任何变化。但页面上好像并没有变化啊,因为我们只是调了一下forceUpdate
并没有来做任何的更新操作。
当然又有人要说了,我们没有写shouldComponentUpdate
方法,那么到底有没有调用这个方法,那我们再把shouldComponentUpdate
方法加上测试一下呗:
class Count extends React.Component { state = { count: 0 }; componentWillUpdate() {...} componentDidUpdate() {...} shouldComponentUpdate() { console.log("Count-shouldComponentUpdate"); return false; } render() {...} add = () => {...}; unmount = () => {...}; force = () => {...} }
我们让其他代码保持不变,让shouldComponentUpdate
方法返回false
,看看forceUpdate
到底会不会受到shouldComponentUpdate
的限制,那我们来看一下效果:
控制台中已经正常按照顺序打印出了整个强制更新流程的钩子调用情况,但是并没有调用shouldComponentUpdate
,可见我们确实是已经成功触发了forceUpdate
流程。
当我们学完了setState
和forceUpdate
这两个流程之后有没有觉得react
设计得很巧妙?你修改state
我可以帮你触发更新流程,或者你只想修改state
不想更新组件,那么我们也可以把阀门关上,不更新组件,或者你有特殊需求,只想更新组件不想改state
那么我们用forceUpdate
方法也可以完成。这样就使得整个组件的灵活性就大大提高了。
总结
forceUpdate
比setState
少一个shouldComponentUpdate
环节forceUpdate
与setState
的本质区别就是forceUpdate
不对state
做任何更改forceUpdate
不受shouldComponentUpdate
方法的限制
Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.
Link of this article:https://work.lynchow.com/article/lifecycle_forceupdate_old/