事件流程
- 事件捕获
- 事件目标
- 事件冒泡
- 事件委托
- 先绑定先执行
事件系统变更
-
更改事件委托
- 首先第一个修改点就是更改了事件委托绑定节点,在16版本中,React都会把事件绑定到页面的document元素上,这在多个React版本共存的情况下就会虽然某个节点上的函数调用了
event.stopPropagation()
,但还是会导致另外一个React版本上绑定的事件没有被阻止触发,所以在17版本中会把事件绑定到render函数的节点上
- 首先第一个修改点就是更改了事件委托绑定节点,在16版本中,React都会把事件绑定到页面的document元素上,这在多个React版本共存的情况下就会虽然某个节点上的函数调用了
-
去除事件池
- 17版本中移除了事件对象池,这是因为 React 在旧浏览器中重用了不同事件的事件对象,以提高性能,并将所有事件字段在它们之前设置为 null。在 React 16 及更早版本中,使用者必须调用
event.persist()
才能正确的使用该事件,或者正确读取需要的属性
- 17版本中移除了事件对象池,这是因为 React 在旧浏览器中重用了不同事件的事件对象,以提高性能,并将所有事件字段在它们之前设置为 null。在 React 16 及更早版本中,使用者必须调用
//合成事件的统一代理处理函数
function dispatchEvent(event) {
let { target, type } = event;//target=button type =click
let eventType = `on${type}`;//onclick
let syntheticEvent = createSyntheticEvent(event);
updateQueue.isBatchingUpdate = true;//事件函数执行前先设置批量更新模式为true
//在此我们要模拟React事件的冒泡
while (target) {
let { store } = target;
let handler = store && store[eventType]
handler && handler(syntheticEvent);
//在执行handler的过程中有可能会阻止冒泡
if (syntheticEvent.isPropagationStopped) {
break;
}
target = target.parentNode;
}
updateQueue.isBatchingUpdate = false;
updateQueue.batchUpdate();
}
/**
* 为什么React不会原生事件对象直接传给事件处理函数
* 1.为了兼容性 像jquery一样,抹平浏览器的差异
* @param {*} nativeEvent
* @returns
*/
function createSyntheticEvent(nativeEvent) {
let syntheticEvent = {};
for (let key in nativeEvent) {//把原生事件上的属性拷贝到合成事件对象上去
syntheticEvent[key] = nativeEvent[key];
}
syntheticEvent.nativeEvent = nativeEvent;
syntheticEvent.isDefaultPrevented = false;
syntheticEvent.isPropagationStopped = false;
syntheticEvent.preventDefault = preventDefault;
syntheticEvent.stopPropagation = stopPropagation;
return syntheticEvent;
}
function preventDefault() {
this.defaultPrevented = true;
const event = this.nativeEvent;
if (event.preventDefault) {
event.preventDefault();
} else {//IE
event.returnValue = false;
}
this.isDefaultPrevented = true;
}
function stopPropagation() {
const event = this.nativeEvent;
if (event.stopPropagation) {
event.stopPropagation();
} else {//IE
event.cancelBubble = true;
}
this.isPropagationStopped = true;
}