成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Vue.js設(shè)計與實現(xiàn)之十三-渲染器的核心功能:掛載與更新02

開發(fā) 前端
在Vue.js的事件處理先要解決的問題,就是如何在虛擬節(jié)點中描述事件,事件是一種特殊的屬性,在vnode.props對象中以字符串on開頭的屬性都被視作事件。

1、寫在前面

在上篇文章中介紹了虛擬節(jié)點的掛載與更新,以及虛擬DOM節(jié)點上的屬性設(shè)置,封裝了新的卸載函數(shù)unmount。那么,虛擬節(jié)點上的事件又是如何處理的呢,同一個事件設(shè)置多個處理函數(shù),同一個元素綁定多個事件,觸發(fā)事件和綁定事件的時機問題應(yīng)該如何處理?

2、事件的處理

在Vue.js的事件處理先要解決的問題,就是如何在虛擬節(jié)點中描述事件,事件是一種特殊的屬性,在vnode.props對象中以字符串on開頭的屬性都被視作事件。

const vnode = {
type:"p",
props:{
// 同一個事件多個事件處理函數(shù)
onClick:[
()=>{
//...
},
()=>{
//...
}
],
// 同一個元素綁定多個事件
onContextMenu(){
//...
}
},
children:"text"
}
renderer.render(vnode, document.querySelector("#app"));

在上面代碼中,我們看到同一的DOM元素上可以綁定多個事件,同一個事件上又可以有多個事件處理函數(shù)。多次我們修改patchProps函數(shù)中事件處理相關(guān)代碼得到:

patchProps(el, key, prevValue, nextValue){
if(/^on/.test(key)){
const invokers = el._vei || (el._vei = {});
let invoker = invokers[key];
const name = key.slice(2).toLowerCase();
if(nextValue){
if(!invoker){
invoker = el._vei[key] => {
//invoker.value是數(shù)組時,遍歷逐個調(diào)用事件處理函數(shù)
if(Array.isArray(invoker.value)){
invoker.value.forEach(fn=>fn(e));
}else{
invoker.value(e);
}
}
invoker.value = nextValue;
el.addEventListener(name, invoker);
}else{
invoker.value = nextValue;
}
}else if(key === "class"){
//...
}else if(shouleSetAsProps(el, key, nextValue)){
//...
}else{
//...
}
}
}

在上面代碼中,先通過/^on/.test(key)檢測元素上以on開頭的屬性,在綁定事件時偽造事件處理函數(shù)invoker

  • 如果invoker不存在時,將invoker作為事件處理函數(shù),緩存到el._vei屬性中
  • 將真正的事件處理函數(shù)設(shè)置為invoker.value屬性的值,偽造的事件處理函數(shù)invoker綁定到元素上

將el._vei的數(shù)據(jù)結(jié)構(gòu)設(shè)計為一個對象,鍵即為事件名稱,值為對應(yīng)的事件處理函數(shù),這樣就不會出現(xiàn)事件覆蓋的現(xiàn)象。當(dāng)上面invoker.value的類型是數(shù)組時,數(shù)組中的每個元素都是一個獨立的事件處理函數(shù),且這些事件處理函數(shù)都能夠正確綁定到對應(yīng)元素上。

3、事件冒泡與更新時機問題

在事件處理中,需要注意處理事件冒泡和更新時機結(jié)合導(dǎo)致的問題,事件觸發(fā)的時間會早于事件處理函數(shù)被綁定的時間。

const {effect, ref} = VueReactivity;
const bol = ref(false);
effect(()=>{
//創(chuàng)建vnode
const vnode = {
type:"div",
props:bol.value ? {
onClick(){
//...
}
}:{},
children:[{
type:"p",
props:{
onClick(){
bol.value = true;
}
},
children:"pingping"
}]
}
//渲染vnode
renderer.render(vnode, document.querySelector("#app"));
})

在上面代碼中進行理論分析,首次渲染后由于bol.value的初始值為false,對此渲染器并不會給div元素綁定點擊事件。在鼠標(biāo)點擊p元素后,bol.value的值變更為true,看到點擊事件會從子元素p冒泡到父元素div上,但是div元素又沒有綁定事件,因此啥也不發(fā)生。

但是,事實上在點擊p元素時,父元素div的click事件觸發(fā)了執(zhí)行函數(shù)的執(zhí)行。這是因為bol是個響應(yīng)式數(shù)據(jù),在點擊p元素后,bol.value的值發(fā)生改變,會觸發(fā)副作用函數(shù)的重新執(zhí)行。而在更新階段,渲染器會給div元素綁定click事件,在更新完后點擊事件才從p元素冒泡到div元素。

觸發(fā)事件的時機與事件綁定的時機的聯(lián)系

在一個事件觸發(fā)時,目標(biāo)元素上還沒有綁定相關(guān)的事件處理函數(shù),因此屏蔽所有綁定事件時機要晚于觸發(fā)時間的事件處理函數(shù)的執(zhí)行。

patchProps(el, key, prevValue, nextValue){
if(/^on/.test(key)){
const invokers = el._vei || (el._vei = {});
let invoker = invokers[key];
const name = key.slice(2).toLowerCase();
if(nextValue){
if(!invoker){
invoker = el._vei[key] => {
//e.timeStamp是事件發(fā)生的時間,如果事件觸發(fā)的時機早于事件綁定的時間,則不執(zhí)行事件處理函數(shù)
if(e.timeStamp < invoker.attached) return;
//invoker.value是數(shù)組時,遍歷逐個調(diào)用事件處理函數(shù)
if(Array.isArray(invoker.value)){
invoker.value.forEach(fn=>fn(e));
}else{
invoker.value(e);
}
}
invoker.value = nextValue;
// 添加invoker.attached屬性,存儲事件處理函數(shù)被綁定的時間
invoker.attached = performance.now();
el.addEventListener(name, invoker);
}else{
invoker.value = nextValue;
}
}else if(key === "class"){
//...
}else if(shouleSetAsProps(el, key, nextValue)){
//...
}else{
//...
}
}
}

在上面代碼中,給偽造的事件處理函數(shù)添加了invoker.attached屬性,用于存儲事件處理函數(shù)被綁定的時間。在invoker執(zhí)行的時候,通過事件對象e.timeStamp獲取事件發(fā)生的時間,比較兩者的時間,如果事件觸發(fā)的時機早于事件綁定的時間,則不執(zhí)行事件處理函數(shù)。

4、寫在最后

在本文中主要討論了事件的處理,介紹了在虛擬節(jié)點上綁定事件,如何綁定和更新事件。同時,還介紹了如何處理觸發(fā)事件與更新時機的問題,屏蔽所有綁定事件時機要晚于觸發(fā)時間的事件處理函數(shù)的執(zhí)行。

責(zé)任編輯:姜華 來源: 前端一碼平川
相關(guān)推薦

2022-04-19 23:01:54

Vue.jsDOM節(jié)點DOM樹

2022-04-18 08:09:44

渲染器DOM掛載Vue.js

2022-04-04 16:53:56

Vue.js設(shè)計框架

2022-04-01 08:08:27

Vue.js框架命令式

2022-04-25 07:36:21

組件數(shù)據(jù)函數(shù)

2022-04-12 08:08:57

watch函數(shù)options封裝

2022-04-03 15:44:55

Vue.js框架設(shè)計設(shè)計與實現(xiàn)

2022-04-11 08:03:30

Vue.jscomputed計算屬性

2022-05-03 21:18:38

Vue.js組件KeepAlive

2022-04-14 09:35:03

Vue.js設(shè)計Reflect

2022-04-05 16:44:59

系統(tǒng)Vue.js響應(yīng)式

2022-04-26 05:55:06

Vue.js異步組件

2022-04-17 09:18:11

響應(yīng)式數(shù)據(jù)Vue.js

2022-04-09 17:53:56

Vue.js分支切換嵌套的effect

2022-04-16 13:59:34

Vue.jsJavascript

2022-04-12 08:09:22

Nodejs前端面試題

2019-04-01 19:38:28

Vue.jsJavascript前端

2010-08-13 11:02:27

Flex渲染器

2016-11-01 19:10:33

vue.js前端前端框架

2009-07-15 13:48:26

Swing模型和渲染器
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美一级在线观看 | 欧美精品一二三 | 一级毛片视频 | 羞视频在线观看 | 欧美一区二区在线观看 | 91久久国产综合久久 | 色播久久久 | 亚洲欧美在线观看视频 | 免费黄色在线观看 | 国产成人免费网站 | 射久久 | 一级片网址 | 99九色| 免费一区| 久久综合久久综合久久综合 | 亚洲电影在线播放 | 日韩a视频| 激情91| 国产精品久久一区 | 亚洲精品久久久久中文字幕欢迎你 | 欧美激情久久久 | 亚洲日本欧美日韩高观看 | 国产片侵犯亲女视频播放 | 欧美久久一区二区 | 亚洲一区二区av在线 | 欧美激情欧美激情在线五月 | 日韩av网址在线观看 | 日韩中文字幕一区二区三区 | 97伦理最新伦理 | 伊人网站视频 | 中文在线观看视频 | 欧美日韩综合 | 新91 | 午夜免费视频观看 | 国产精品久久国产精品 | 国产三区视频在线观看 | 暖暖日本在线视频 | 99tv| 七七婷婷婷婷精品国产 | 在线观看中文字幕 | 中文字幕一二三区 |