接上文,
React流程图:
https://bogdan-lyashenko.gith...
回到最初
在流程图中,也许你已经注意到,setState方法可以通过几种方式触发,更准确的说,可以分为是否由外部引起的(也就是是否由用户触发)。让我们看下如下两个列子,第一个中,
是由鼠标点击触发的,第二个中,是在componentDidMount中由setTimeout方法中被触发的。
为什么会有这些不同呢?如果你还有印象,在之前的文章中,React对于更新的处理是批量的,也就是说,一系列更新操作会通过某种方式被收集起来,然后统一刷新到页面上。当鼠标事件发生时,组件的最外层会进行处理,然后通过几层包装器的处理后,会开始进行批量更新操作。注意,批量更新操作的前提是确保ReactEventListener处于enabled状态,而且,在前文提到过,在组件的挂载阶段,ReactReconcileTransaction包装器中的一个会先关闭它,以确保整个挂载过程的安全。 至于setTimeout中的调用,则是在将组件放入dirtyComponents列表之前,React会确保事务处于打开状态,在这之后,关闭事务包装器,然后将更新刷新到页面上。
正如你所知,React实现了合成事件,在一下原生事件包裹了一些合成语法糖。在这之后,React会将这些事件处理成常见到样子。看下如下代码里到注释:
为了更好地开发,通过模拟真实游览器事件,我们可以得到更好开发工具整合过程(To help development we can get better dev tool integration by simulating a real browser event’)
var fakeNode = document.createElement('react');
ReactErrorUtils.invokeGuardedCallback = function (name, func, a) {
var boundFunc = func.bind(null, a);
var evtType = 'react-' + name;
fakeNode.addEventListener(evtType, boundFunc, false);
var evt = document.createEvent('Event');
evt.initEvent(evtType, false, false);
fakeNode.dispatchEvent(evt);
fakeNode.removeEventListener(evtType, boundFunc, false);
};
回到我们的更新流程,我们在这里总结下大概的步骤:
1 调用setState方法
2 如果批量事务未处于开启状态,则打开该事务
3 将受影响组件添加到dirtyComponents列表里
4 通过调用ReactUpdates.flushBatchedUpdates方法关闭事务,也就意味着开始对dirtyComponents列表进行处理。
(未完待续)