上一篇文章中,批量更新采用的是手动控制的方式。但是我们实际的开发中,react并没有让用户手动控制批量更新,所以本节目标实现一个自动的批量更新。
1、修改index.js代码
修改前:
修改后:
// index.jshandleClick = () => {this.setState({number: this.state.number + 1},() => {console.log(`111`, this.state.number)})console.log(this.state.number)this.setState({number: this.state.number + 1})console.log(this.state.number)setTimeout(() => {this.setState({number: this.state.number + 1})console.log(this.state.number)}, 0)}
2、合成事件
react事件采用的合成事件,并不是原生的事件。
前置知识:https://www.yuque.com/linhe-8mnf5/fxyxkm/tnkpyg#k2Xds 第二点事件
2.1 修改react-dom.js
修改react-dom.js文件的updateProps方法。之前是直接copy属性绑定到真实dom,现在绑定合成事件到真实dom。

2.2 event.js编写
// event.jsimport { updateQueue } from "./Component";/*** 给真实dom添加事件处理函数* 合成事件的作用:* 1.可以做兼容处理(不同浏览器的event是不一样的);* 2.可以在自己写的处理函数之前和之后做一些事情,比如 updateQueue.isBatchingUpdate = true 之后 updateQueue.batchUpdate()* @param {*} dom 真实dom* @param {*} eventType 事件类型* @param {*} listener 监听函数*/export function addEvent(dom, eventType, listener) {let store = dom.store || (dom.store = {})store[eventType] = listener //store.onclick = handleClickif (!document[eventType]) {// 事件委托,统一代理到document上document[eventType] = dispatchEvent}}let syntheticEvent = {}function dispatchEvent(event) {let { target, type } = event //事件源:dom元素 、type:type=clickconst eventType = `on${type}` // onclick// 设置批量更新updateQueue.isBatchingUpdate = true// 拷贝元素事件到合成事件createSyntheticEvent(event)// 向上冒泡while(target){const { store } = targetconst listener = store && store[eventType]// 事件处理listener && listener.call(target, syntheticEvent)target = target.parentNode}// 清理eventfor(let key in syntheticEvent){syntheticEvent[key] = null}// 批量更新updateQueue.batchUpdate()}// 拷贝原生事件到合成事件function createSyntheticEvent(nativeEvent) {for(let key in nativeEvent){syntheticEvent[key] = nativeEvent[key]}}
需要注意向上冒泡的处理逻辑:
<button onClick={handleClick}></button>// 如果不处理合成事件的冒泡,此处不起作用<button><span onClick={handleClick}></span></button>
3、实现效果

4、源代码
本文地址:https://gitee.com/linhexs/react-write/tree/5.synthetic-event/
