因为解决6566 issue,add函数这里做出了巨大的变化

来源:8-7 event(6)

godlanbo

2021-04-01

如题,因此找不到关于withMacroTask的相关实现了,但是我看的版本(2.6.11)的实现不是很懂,想请教一下关于2.6.11版本中关于add函数的实现。

写回答

2回答

ustbhuangyi

2021-04-03

其实注释已经说的比较清楚了,它说的是一种 DOM 嵌套的情况,比如内层元素触发了点击事件,事件会向外层冒泡,但是 mircotask 会比事件冒泡还要快,所以在事件冒泡的时候,会触发组件的更新和重新渲染,重新渲染后事件冒泡到外层,如果外层监听了点击事件,又会再次触发这个点击事件。

但是,实际上这种情况往往是不符合预期的,所以 Vue.js 做了一些修改,在添加事件回调函数的时候,也就是组件渲染的过程中,记录一下当前的刷新时间,作为 attachedTimestamp,然后对原始的事件回调函数做了封装,这样当 handler 执行的时候,会判断 e.timeStamp >= attachedTimestamp 这个条件是否满足。

再回到我们刚才说的情况,当事件冒泡到外层触发点击事件,由于是由第一个点击事件冒泡上来的,那么它的 e.timeStamp,也就是原始事件触发的时间,肯定是小于 attachedTimestamp,因为在事件冒泡之间触发了重新渲染,更新了 attachedTimestamp,这样就不满足条件,那么冒泡到外层的原始事件回调函数就不会再执行。

2
1
godlanbo
非常感谢,看了老师的解释,又再看了下原issue的例子,一下明白了
2021-04-08
共1条回复

ustbhuangyi

2021-04-02

贴一下相关的代码?

0
1
godlanbo
function add ( name: string, handler: Function, capture: boolean, passive: boolean ) { // async edge case #6566: inner click event triggers patch, event handler // attached to outer element during patch, and triggered again. This // happens because browsers fire microtask ticks between event propagation. // the solution is simple: we save the timestamp when a handler is attached, // and the handler would only fire if the event passed to it was fired // AFTER it was attached. if (useMicrotaskFix) { const attachedTimestamp = currentFlushTimestamp const original = handler handler = original._wrapper = function (e) { if ( e.target === e.currentTarget || e.timeStamp >= attachedTimestamp || e.timeStamp <= 0 || e.target.ownerDocument !== document ) { return original.apply(this, arguments) } } } target.addEventListener( name, handler, supportsPassive ? { capture, passive } : capture ) } 这是目前add函数的实现,由于字数限制,我删掉了一些注释
2021-04-03
共1条回复

Vue.js 源码深入解析 深入理解Vue实现原理

全方位讲解 Vue.js 源码,进阶高级工程师

4986 学习 · 1038 问题

查看课程