vue中 点击事件的写法_vue中的事件:原生事件与自定义事件__Vue.js
模板編譯 processAttrs
對于ast attributes處理(v-on/@)
利用onRE與dirRE來捕獲事件
這里最重要的就是dynamic的判斷,vue中可以用動態(tài)參數(shù)來命名事件名稱,如@[prop],prop為data中的值。不過通常都是一個靜態(tài)的事件名稱如 @click
另一個核心方法就是addHandler
addHandler 往AST上添加events屬性
1. 這里會對動態(tài)事件名稱進(jìn)行一些處理,也會對right,middle修飾符處理,另外對capture, passive, once的事件名稱做了標(biāo)記。分別添加 !, ~, # 符號。然后刪除了對應(yīng)屬性值
2. 參數(shù)value為@click="handler"例子中的handler,在此處還在編譯階段handler本質(zhì)上是一個string。然后對value做了處理,記錄了模板解析event時候start和end的位置。
3. 對于單個事件有多回調(diào)函數(shù)綁定的情況,添加了一個important參數(shù),以此來提前觸發(fā)當(dāng)前回調(diào)函數(shù)的執(zhí)行
4. 另外,這里對鼠標(biāo)的right和middle做了處理,在處理只有刪除了對應(yīng)屬性值。對于鍵盤的事件沒有做處理
AST -> code
修飾符:modifierCode
上面已經(jīng)提到過了,本質(zhì)上模板編譯的時候會利用正則處理各種修飾符,然后根據(jù)對應(yīng)關(guān)鍵詞的生成代碼。如常用的stop,prevent。
核心方法就是src/compiler/codegen/events.js的genHandler方法,以下是分析:
1. genHandlers
該方法就是簡單的遍歷events對象的鍵值對然后,對有無native修飾符與是否為dynamic事件做一個處理,其核心方法就是調(diào)用genHandler
genHandler
一些參數(shù)判斷
事件函數(shù)的多種寫法
在官方文檔中演示了事件回調(diào)函數(shù)的多種寫法,這些寫法都在模板編譯過程中進(jìn)行了識別
下方三個正則表達(dá)式是模板編譯時對event寫法的判斷依據(jù),下面會有更詳細(xì)的注釋
1. 路徑類寫法
2. 箭頭函數(shù),匿名函數(shù)
3. 表達(dá)式 handler($event), a = 1
在vue中通常通過@click="handle($event)"來獲取event對象,其實(shí)這里是vue在模板中做了一層包裹,將function($event){}套在handle($event)外部。
有修飾符的情況
修飾符在ast生成的過程中就已經(jīng)捕獲了,vue中對event事件的修飾符處理如下
先對修飾符做一個處理
最后座一層包裹,因?yàn)檫@里對鍵盤事件也做了處理,因此一定要拿到event對象
genCode
在處理完這些之后會生成字符串on:"…"/nativeOn:"…",最后生成render函數(shù)
組件初始化
組件初始化簡單地說就是先對options做各種處理,最后執(zhí)行渲染watcher,生成頁面。
對native events的處理:
platforms/web/runtime/patch.js中有
const patch = createPatchFunction({nodeOps, modules})
modules源自:web/runtime/modules/index,導(dǎo)出含生命周期的對象**(非created周期)**
createPatchFunction
createPatchFunction往hooks內(nèi)添加了updateDOMListeners,hooks為**并非是**組件的生命周期函數(shù)。在組件create與updated的時候就會觸發(fā)updateDOMListeners函數(shù)。注冊事件。
注意點(diǎn): 這里create并非是組件created的**周期函數(shù)。**是在真實(shí)節(jié)點(diǎn)創(chuàng)建之后才會觸發(fā)鉤子,因此是可以拿到真實(shí)節(jié)點(diǎn)的。
updateDOMListeners
在調(diào)用modules.create的hook的時候觸發(fā)了updateDOMListeners
其作用就是給用addEventListeners與removeEventListeners方法給真實(shí)dom節(jié)點(diǎn)添加事件。
updateListeners
將新舊事件進(jìn)行對比更新。這里的add和remove可以給真實(shí)dom注冊事件,也可以給組價注冊事件。
占位符$vnode的真實(shí)dom事件:createComponent(部分)
對于組件而言,data.on賦值給listeners,把data.nativeOn賦值給data.on
data.on里面存放著的都是原生dom事件,組件內(nèi)部的listeners都是用戶自定義的事件。
因此,在組件patch過程中,創(chuàng)建組件的根節(jié)點(diǎn)的時候,就會把data.on內(nèi)部的原生dom事件注冊在dom上。
因此如果在h5元素使用native如 ,vue就會報錯。這正是因?yàn)樵谶@里做了處理,只有占位符vnode才可以有data.nativeOn的屬性。是h5標(biāo)簽的節(jié)點(diǎn)不會調(diào)用createComponent方法,其data.on在創(chuàng)建節(jié)點(diǎn)的時候會綁定到節(jié)點(diǎn)上。
自定義事件(只針對組件間)
由createComponent函數(shù)可知,listeners存放了自定義事件。
在父子通訊的時候父組件只要v-on/@eventName,就可以監(jiān)聽到子組件emit出來的事件。
_init: initInternalComponent
創(chuàng)建子組件的時候會把占位符$vnode的$listeners傳遞給子組件的$options**(此時data.on已經(jīng)是data.nativeOn,原始的data.on賦值給變量listeners)**
_init: initEvents
調(diào)用updateComponentListeners方法,最后還是調(diào)用了updateListeners方法(見前面文章注釋)。
但是這里不同的是add和remove方法并非是document.addEventListener和document.removeEventListener
add/remove(vue中的發(fā)布訂閱模式):
其實(shí)發(fā)布訂閱模式比較簡單,就不詳細(xì)說明了,主要是add/remove方法。
小結(jié)
其實(shí)本質(zhì)上,還是將父組件注冊的回調(diào)函數(shù)傳給了子組件的_events對象(讓該函數(shù)存在于子組件中),但是看起來像是子組件調(diào)用了父組件的方法
eventBus
對于跨組件的組件通信,利用了vue實(shí)例可以有自身的_events對象,因此在Vue原型上創(chuàng)建一個空的vue實(shí)例,然后將vue所有組件上的函數(shù)都注冊在這個實(shí)例對象的_events對象上,一次達(dá)到跨組件通信的目的
Vue.prototype.$bus=new Vue()
第三種情況:v-on="$listeners"
$listeners就是vnode.data.on的別稱,因此通過$listeners就可以拿到父組件注冊的非native事件。在爺孫組件通信的是可以使用$listeners通過父級組件將爺孫組件關(guān)聯(lián)。
grand組件:
father組件:? // 此處是grand的事件
son組件:this.$emit(“test”) // 將father的$listeners傳入son,而father的$listeners包含grand的事件,因此就將grand的事件傳入了son中。
AST解析
在模板解析的時候會用正則匹配v-on,對于v-on="$listeners",vue將這種寫法視為指令(directive),有不同的策略
on指令
_g
這里將$listeners對象與data.on進(jìn)行合并,通過v-on指令我們可以一次性對組件注冊多個事件。
最后
vue的事件基本上就是這樣,其實(shí)這里面牽扯到了最核心的組件初始化和更新流程,關(guān)于此部分在本文中并沒有明確說明,只是大概提了一下,一是要單純靠文字說明費(fèi)時費(fèi)力(代碼含有大量遞歸),而是本文重點(diǎn)是關(guān)注vue中的事件,在后面的更深入了解整個機(jī)制后會嘗試說明寫一篇vue組件初始化及更新的文章。
版權(quán)聲明:著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
作者: Simplyme0823
原文鏈接:https://juejin.im/post/6861206075744452622
總結(jié)
以上是生活随笔為你收集整理的vue中 点击事件的写法_vue中的事件:原生事件与自定义事件__Vue.js的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hbuild json红叉_MUI+Hb
- 下一篇: core mysql 延迟加载_myba