浅入深出setState(上篇)

2018-07-13 admin

Part one - setState点燃引擎

setState点燃引擎

这是一个React组件实现组件可交互所需的流程,render()输出虚拟DOM,虚拟DOM转为DOM,再在DOM上注册事件,事件触发setState()修改数据,在每次调用setState方法时,React会自动执行render方法来更新虚拟DOM,如果组件已经被渲染,那么还会更新到DOM中去。 这个过程,setState就像一个点燃引擎的打火石,发动了React核心的调度层,然后直至渲染层的改变。

Part two - setState是异步的

刚接触React的同学,对React的setState的使用偶尔会有一些偏颇,出现一些意料之外的情况。 比如:

onClickForReset=()=>{
    this.setState({value: []});
    // 此刻立马取this.state做一些同步操作
    console.log(this.state.value);
}

或者是

increateCount(){
    this.setState({count: this.state.count + 1});
    this.setState({count: this.state.count + 1});
    this.setState({count: this.state.count + 1});
}

我们可以看一个现在的例子: https://codesandbox.io/s/qqy9n5o2m9

https://codesandbox.io/s/qqy9n5o2m9

setState比较熟练的同学可以跳过这一段代码,但是有些刚学会使用React的同学经常会犯这个错误,一开始我只能粗暴地说:

  1. setState是异步的,不会立即改变state的值。
  2. 多次setState调用生成的效果会合并。
  3. 第二个参数可以是一个回调函数。
  4. setState可以接受一个函数(例子改动)

后来我逐渐也在想下面这两个问题,现在这篇文章试图尽量弄清的两件事:

  1. 为什么要把setState设计成异步的,缘由是什么,解决了什么问题,有什么好处?
  2. 如何实现异步的setState,整体原理是怎样的,有没有什么特殊的骚操作?

我们可以自己也想一想,下面留给大家一片空白区。😝

<div style=“background:#fff;width:100%;height:500px;margin-bottom:30px;”></div>

好,我们带着这两个问题和自己的猜想,试图一探究竟。

Part three - 为什么要异步

简单的来说:在批量多次的更新中,延缓到最后合并渲染是有好处的。

万剑归宗

  1. 保证内部的一致性:首先,我想我们都同意推迟并批量处理重渲染是有益而且对性能优化很重要的,无论 setState() 是同步的还是异步的。那么就算让 state 同步更新,props 也不行,因为当父组件重渲染(re-render )了你才知道 props。
  2. 在批量多次的更新中,延缓到最后合并渲染是有好处的。这一点,和我们熟知的防抖动函数的出发点类似,我们普遍认为在许多情况下在同一时间段,频繁setState触发渲染,连续同步效率很低,对性能有极大损耗。

我们来看下setState引发组件的更新过程就知道了:

setState引发组件的更新过程

每一次setState如果都引发一次组件更新,走完一圈生命周期,实在是有点粗糙和浪费,生命周期函数为纯函数性能应当还能够接受,可是render函数内返回的虚拟DOM去做比较这个就比较费时间了。

直观的感受是,React将多个setState产生的修改放在一个队列里,缓一缓,攒在一起,等待时机,觉得差不多了再引发一次更新过程。这样,在每次更新过程中,会把积攒的setState结果合并,做一个merge的动作,节省render触发的频率。 这样,对于开发者而言,可以在同步代码中随意多行调用setState函数而不用担心重复setState重复render的问题。

然后,总是被大家误用不理解的也是这一点,所以后来,setState方法的第二个参数慢慢被进入大家的视野了,作为回调函数可以再次拿到新的this.state值。

再后来,一个setState函数的隐藏功能进入了大家的视野,那就是,setState可以接受一个函数作为参数。

更多:https://github.com/facebook/react/issues/11527#issuecomment-360199710

Part four - 怎么实现异步

在此之前,我们来看一个例子…可能会颠覆你对setState的认识

我们可以直接打开在线案例:https://codesandbox.io/s/vq1nqkvyw5

setState真的是异步吗

提问:实际运行结果是怎么样的?好吧现在下

Part five - 彩蛋:setState真的是异步吗?

我们上面一个例子告诉我们:

No! 可能是同步 超出React生命周期和React代理事件之外都是同步

预知后事如何,请看下半篇。

原文链接:https://segmentfault.com/a/1190000015615057

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-35871.html

文章标题:浅入深出setState(上篇)

相关文章
JavaScript深入之类数组对象与
类数组对象 所谓的类数组对象: 拥有一个 length 属性和若干索引属性的对象 举个例子: var array = [&#x27;name&#x27;, &#x27;age&#x27;, &#x27;sex&#x27;]; var ...
2017-05-27
浅谈JavaScript中指针和地址
个人理解:指针只是指向内存的一个索引;而地址则是内存中确切的位置。 下面是函数中关于指针和地址一个小例子: function sum(num1,num2){ return num1+num2; } alert(sum(10,10));  &...
2017-03-27
HTML5之WebSocket入门3 -通信模型socket.io
socket.io为什么会诞生呢?请看下面文字说明。 为什么需要socket.io? node.js提供了高效的服务端运行环境,但是由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服...
2017-03-29
nodejs导出excel的方法
本文实例讲述了nodejs导出excel的方法。分享给大家供大家参考。具体如下: nodejs 对查询数据生成excel并下载,采用方式先生成本excel文件,然后再下载;通过比较采用excel-export插件代码如下: excel.js...
2017-03-27
如何用js 实现依赖注入的思想,后端框架思想搬到前端来
大家在做些页面的时候,很多都是用ajax实现的,在显示的时候有很多表单提交的add或者update操作,显然这样很烦,突然想到了一个比较好的方法,下面给大家分享下如何用js 实现依赖注入的思想,后端框架思想搬到前端来。 应用场景: 前后端一...
2017-03-29
深入分析JSON编码格式提交表单数据
以JSON编码格式提交表单数据是HTML5对WEB发展进化的又一大贡献,以前我们的HTML表单数据是通过key-value方式传输的服务器端,这种形式的传输对数据组织缺乏管理,形式十分原始。而新出现的JSON格式提交表单数据方法,将表单里的...
2017-03-25
浅析Node.js的Stream模块中的Readable对象
我一直都很不愿意扯 nodejs 的流,因为从第一次看到它我就觉得它的设计实在是太恶心了。但是没办法,Stream 规范尚未普及,而且确实有很多东西都依赖了 nodejs 的流来实现的,所以我也只能捏着鼻子硬着头皮来扯一扯这又臭又硬的 no...
2017-03-27
浅谈Javascript的静态属性和原型属性
文章给各位介绍Javascript的静态方法和原型方法一个例子,如果大家对于Javascript的静态方法和原型方法不了解可以和小编一起来看看。 一段代码,了解静态方法和实例方法: &lt;script&gt; &#x2F;...
2017-03-23
为什么 JavaScript 会在移动端中胜出?
JavaScript并不是世界上最优美的编程语言。正因如此,一个世界级的专家写了一本关于这个语言的“精粹 ”的书。这本书的名字是“深度挖掘javascript的亮点”,因为优秀的东西被埋的相当深。即便如此,它还是迅速地称为世界上最受欢迎的语...
2015-12-25
浅谈Javascript数组索引
从题目说起,之所以是不完全,是因为有些东西比如数组的方法怎么用这个我都不打算讲,因为那个看一下都会,下面讲的都是我觉得重要的,只关于数组对象本身。另外,由于我的Javascript实战经验不多,所以可能有些东西没涉及到,有些内容说的有误,请...
2017-03-27
回到顶部