您好,登錄后才能下訂單哦!
這篇文章主要講解了“Vue2模版指令元素綁定事件執行順序是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Vue2模版指令元素綁定事件執行順序是什么”吧!
version: 2.6.14
某日,業務需要我需要在按鈕點擊之前驗證某些條件,如果不符合即不執行click內的業務代碼。思前想后,寫一個指令不就可以了。做到既不改動原有的業務代碼,又可以移植。
<template> <button v-capture @click="handleClick">button</button> </template> <script> export default { methods: { handleClick(){ console.log(1) } }, directives: { capture: { bind(el) { el.captureHandler = (e) => { // 驗證條件 console.log(2) e.stopPropagation() }; el.addEventListener("click", el.captureHandler); }, unbind(el) { el.removeEventListener("click", el.captureHandler); } } } } </script>
以上就是偽代碼,乍一看沒啥問題。
實際一運行,發現1和2都打印出來了,而且1還是在2之前運行的。
這樣一看模版上綁定的事件執行是在自定義指令綁定事件之前的。
翻開谷歌,也沒有找到相關案例。
我們都知道vue的SFC最終還是會被編譯成js文件,最終模板會被編譯成vnode,
元素上綁定的事件會轉換成vnode上的一個對象
{ // .... on: { click: 'handleClick' } }
那就找一找這個對象在哪邊使用的
runtime中搜索addEventListener
, 因為這個事件綁定上DOM中才有的事件,所以只會在web中了
// src/platforms/web/runtime/modules/events.js export default { create: updateDOMListeners, update: updateDOMListeners, destroy: (vnode: VNodeWithData) => updateDOMListeners(vnode, emptyNode) }
具體實現就先不管
updateDOMListeners
中通過調用了updateListeners
方法,把事件綁定到元素上去
還有就是返回了一個對象,包括create、update、destroy, 這不是很像vue的生命周期函數命名嘛
根據文件依次向上找????
最終在modules/index.js
中導出了
export default [ attrs, klass, events, domProps, style, transition ]
modules
最終在哪里使用的?
就是大名鼎鼎的patch.js
// src/core/vdom/patch.js const { modules, nodeOps } = backend for (i = 0; i < hooks.length; ++i) { cbs[hooks[i]] = [] for (j = 0; j < modules.length; ++j) { if (isDef(modules[j][hooks[i]])) { cbs[hooks[i]].push(modules[j][hooks[i]]) } } }
函數一上來就把modules進行分類,把原來modules上的相關的對象進行合并,
最終cbs會變成一個對象
const cbs = { create: [fn1, fn2, fn3], update: [fn1, fn2, fn3], destroy: [fn1, fn2, fn3], }
具體的執行的時機就不說了
指令是vue的一大特色了,源于angularjs中就有指令這個東西了,vue3中依舊保留了下來
指令中對應以下幾個方法,也可以說是生命周期了
directives: { name: { bind(){}, insert(){}, inserted(){}, componentUpdated(){}, update(){}, unbind(){}, } }
接下來找找指令是什么時候初始化的
全局查找directives
, 其實就這一個文件,那就是它了
// src/core/vdom/modules/directives.js { create: updateDirectives, update: updateDirectives, destroy: function unbindDirectives (vnode: VNodeWithData) { updateDirectives(vnode, emptyNode) } }
可以明顯看到它也是在create
內部周期上調用了bind
方法了
callHook(dir, 'bind', vnode, oldVnode)
回到patch.js
, 可以看到模塊在這里進行了合并,把平臺相關的模塊放在前面,基礎指令和ref放在后面執行了。
同時官方也進行了注釋,先執行內置的方法再執行指令的方法。
// src/platforms/web/runtime/patch.js import baseModules from 'core/vdom/modules/index' import platformModules from 'web/runtime/modules/index' // the directive module should be applied last, after all // built-in modules have been applied. const modules = platformModules.concat(baseModules)
還是注釋沒仔細看,這個文件打開過多少次了。????
改了就可以了嗎
依舊不行。
問題就在addEventListener
身上
拋開vue,看demo
const btn = document.querySelector('#btn') btn.addEventListener('click', () => { console.log(1) }) btn.addEventListener('click', () => { console.log(2) })
HTML 元素重復綁定同一個事件,后者并不會覆蓋前面的,只會有綁定的先后順序
那之前的問題還能解么
在捕獲階段執行事件, 如果不符合條件,則停止事件傳遞。
el.addEventListener("click", el.captureHandler, true);
并且stopImmediatePropagation
還用不了
stopImmediatePropagation可以阻止元素上綁定的其他事件,但是也是按添加順序,阻止之后的事件執行
感謝各位的閱讀,以上就是“Vue2模版指令元素綁定事件執行順序是什么”的內容了,經過本文的學習后,相信大家對Vue2模版指令元素綁定事件執行順序是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。