摘要:模塊在里面,定義了一系列的模塊,這些模塊定義了相應(yīng)的鉤子。主要接受兩個(gè)參數(shù),。傳送門事件模塊待續(xù)。。。源碼解析系列源碼解析一準(zhǔn)備工作源碼解析二函數(shù)源碼解析三對(duì)象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個(gè)人博客地址
模塊
在 ./src/modules 里面,定義了一系列的模塊 , 這些模塊定義了相應(yīng)的鉤子 。這些鉤子會(huì)在 patch 的不同階段觸發(fā),以完成相應(yīng)模塊的功能處理
了解生命周期更多的內(nèi)容,請(qǐng)查看 鉤子
主要的模塊有 :
attributes.ts
class.ts
dataset.ts
eventlisteners.ts
hero.ts
module.ts
props.ts
style.ts
其中 attributes class dataset props 四個(gè)比較簡(jiǎn)單,都是定義了 create update 兩個(gè)鉤子,
eventlisteners hero style 這三個(gè)模塊就復(fù)雜一點(diǎn)。
另外 module.ts 只是定義了這些模塊所用到的一些鉤子
// 定義模塊的鉤子 export interface Module { pre: PreHook; create: CreateHook; update: UpdateHook; destroy: DestroyHook; remove: RemoveHook; post: PostHook; }
接下來(lái)我們來(lái)看看其他的模塊
attributes 模塊文件位置 : ./src/modules/attributes.ts
我們先拉到最后
// 創(chuàng)建以及更新的鉤子 export const attributesModule = { create: updateAttrs, update: updateAttrs } as Module; export default attributesModule;
attributesModule 導(dǎo)出了兩個(gè)方法, 都是調(diào)用了 updateAttrs 。
這個(gè)表示,在創(chuàng)建元素的時(shí)候,以及更新的時(shí)候,都會(huì)觸發(fā)這兩個(gè)鉤子,來(lái)更新 attribute。
updateAttrsupdateAttrs 主要接受兩個(gè)參數(shù),oldVnode、vnode 。
主要邏輯如下:
遍歷新 vnode 所有的屬性,判斷在 oldVnode 中是否相等,修改不相等的屬性
刪除不存在于 vnode 的屬性
代碼如下:
/** * 更新屬性 */ function updateAttrs(oldVnode: VNode, vnode: VNode): void { var key: string, elm: Element = vnode.elm as Element, oldAttrs = (oldVnode.data as VNodeData).attrs, attrs = (vnode.data as VNodeData).attrs; if (!oldAttrs && !attrs) return; if (oldAttrs === attrs) return; oldAttrs = oldAttrs || {}; attrs = attrs || {}; // update modified attributes, add new attributes // 遍歷新的屬性,修改不相等的 for (key in attrs) { const cur = attrs[key]; const old = oldAttrs[key]; if (old !== cur) { if (cur === true) { elm.setAttribute(key, ""); } else if (cur === false) { elm.removeAttribute(key); } else { if (key.charCodeAt(0) !== xChar) { // 如果不是 x 開(kāi)頭 elm.setAttribute(key, cur); } else if (key.charCodeAt(3) === colonChar) { // Assume xml namespace elm.setAttributeNS(xmlNS, key, cur); } else if (key.charCodeAt(5) === colonChar) { // Assume xlink namespace elm.setAttributeNS(xlinkNS, key, cur); } else { elm.setAttribute(key, cur); } } } } // remove removed attributes // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value) // the other option is to remove all attributes with value == undefined // 刪除多余的屬性 for (key in oldAttrs) { if (!(key in attrs)) { elm.removeAttribute(key); } } }class 模塊
文件位置 : ./src/modules/class.ts
與 attribute 類似 , class 也是定義了 create 和 update 兩個(gè)鉤子,統(tǒng)一由 updateClass 處理
這塊邏輯比較簡(jiǎn)單 ,直接看代碼吧
function updateClass(oldVnode: VNode, vnode: VNode): void { var cur: any, name: string, elm: Element = vnode.elm as Element, oldClass = (oldVnode.data as VNodeData).class, klass = (vnode.data as VNodeData).class; // 新老的 className 都沒(méi)有 if (!oldClass && !klass) return; // 新老的 className 沒(méi)變 if (oldClass === klass) return; oldClass = oldClass || {}; klass = klass || {}; // 刪除不存在與新的 classList 的 className for (name in oldClass) { if (!klass[name]) { elm.classList.remove(name); } } // 新增 或刪除 class for (name in klass) { cur = klass[name]; if (cur !== oldClass[name]) { (elm.classList as any)[cur ? "add" : "remove"](name); } } }dataset 模塊
文件位置 : ./src/modules/dataset.ts
與 attribute 類似 , dataset 也是定義了 create 和 update 兩個(gè)鉤子,統(tǒng)一由 updateDataset 處理
這塊邏輯比較簡(jiǎn)單 ,直接看代碼吧
const CAPS_REGEX = /[A-Z]/g; /** * 更新或創(chuàng)建 dataset */ function updateDataset(oldVnode: VNode, vnode: VNode): void { let elm: HTMLElement = vnode.elm as HTMLElement, oldDataset = (oldVnode.data as VNodeData).dataset, dataset = (vnode.data as VNodeData).dataset, key: string; // 不變的情況下不處理 if (!oldDataset && !dataset) return; if (oldDataset === dataset) return; oldDataset = oldDataset || {}; dataset = dataset || {}; const d = elm.dataset; // 刪除多余的 dataset for (key in oldDataset) { if (!dataset[key]) { if (d) { if (key in d) { delete d[key]; } } else { // 將駝峰式改為中劃線分割 eg: userName ----> user-name elm.removeAttribute( "data-" + key.replace(CAPS_REGEX, "-$&").toLowerCase() ); } } } // 修改有變化的 dataset for (key in dataset) { if (oldDataset[key] !== dataset[key]) { if (d) { d[key] = dataset[key]; } else { elm.setAttribute( // 將駝峰式改為中劃線分割 eg: userName ----> user-name "data-" + key.replace(CAPS_REGEX, "-$&").toLowerCase(), dataset[key] ); } } } }props 模塊
文件位置 : ./src/modules/props.ts
與 attribute 類似 , props 也是定義了 create 和 update 兩個(gè)鉤子,統(tǒng)一由 updateProps 處理
這塊邏輯比較簡(jiǎn)單 ,直接看代碼吧
function updateProps(oldVnode: VNode, vnode: VNode): void { var key: string, cur: any, old: any, elm = vnode.elm, oldProps = (oldVnode.data as VNodeData).props, props = (vnode.data as VNodeData).props; if (!oldProps && !props) return; if (oldProps === props) return; oldProps = oldProps || {}; props = props || {}; // 刪除多余的屬性 for (key in oldProps) { if (!props[key]) { delete (elm as any)[key]; } } // 添加新增的屬性 for (key in props) { cur = props[key]; old = oldProps[key]; // key為value的情況,再判斷是否value有變化 // key不為value的情況,直接更新 if (old !== cur && (key !== "value" || (elm as any)[key] !== cur)) { (elm as any)[key] = cur; } } }eventlisteners 模塊
eventlisteners 這一塊內(nèi)容稍微多一點(diǎn),故將其獨(dú)立出來(lái)一個(gè)章節(jié)。 傳送門 : 事件
style 模塊待續(xù)。。。
hero 模塊待續(xù)。。。
snabbdom源碼解析系列snabbdom源碼解析(一) 準(zhǔn)備工作
snabbdom源碼解析(二) h函數(shù)
snabbdom源碼解析(三) vnode對(duì)象
snabbdom源碼解析(四) patch 方法
snabbdom源碼解析(五) 鉤子
snabbdom源碼解析(六) 模塊
snabbdom源碼解析(七) 事件處理
個(gè)人博客地址
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100419.html
摘要:閱讀源碼的時(shí)候,想了解虛擬結(jié)構(gòu)的實(shí)現(xiàn),發(fā)現(xiàn)在的地方。然而慢慢的人們發(fā)現(xiàn),在我們的代碼中布滿了一系列操作的代碼。源碼解析系列源碼解析一準(zhǔn)備工作源碼解析二函數(shù)源碼解析三對(duì)象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個(gè)人博客地址 前言 虛擬 DOM 結(jié)構(gòu)概念隨著 react 的誕生而火起來(lái),之后 vue2.0 也加入了虛擬 DOM 的概念。 閱讀 vue 源碼的時(shí)候,想了解...
摘要:這種解決方式也是相當(dāng)優(yōu)雅,值得學(xué)習(xí)源碼解析系列源碼解析一準(zhǔn)備工作源碼解析二函數(shù)源碼解析三對(duì)象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個(gè)人博客地址 事件處理 我們?cè)谑褂?vue 的時(shí)候,相信你一定也會(huì)對(duì)事件的處理比較感興趣。 我們通過(guò) @click 的時(shí)候,到底是發(fā)生了什么呢! 雖然我們用 @click綁定在模板上,不過(guò)事件嚴(yán)格綁定在 vnode 上的 。 event...
介紹 這里是 typescript 的語(yǔ)法,定義了一系列的重載方法。h 函數(shù)主要根據(jù)傳進(jìn)來(lái)的參數(shù),返回一個(gè) vnode 對(duì)象 代碼 代碼位置 : ./src/h.ts /** * 根據(jù)選擇器 ,數(shù)據(jù) ,創(chuàng)建 vnode */ export function h(sel: string): VNode; export function h(sel: string, data: VNodeData...
摘要:對(duì)象是一個(gè)對(duì)象,用來(lái)表示相應(yīng)的結(jié)構(gòu)代碼位置定義類型定義類型選擇器數(shù)據(jù),主要包括屬性樣式數(shù)據(jù)綁定時(shí)間等子節(jié)點(diǎn)關(guān)聯(lián)的原生節(jié)點(diǎn)文本唯一值,為了優(yōu)化性能定義的類型定義綁定的數(shù)據(jù)類型屬性能直接用訪問(wèn)的屬性樣式類樣式數(shù)據(jù)綁定的事件鉤子創(chuàng)建對(duì)象根據(jù)傳入的 vnode 對(duì)象 vnode 是一個(gè)對(duì)象,用來(lái)表示相應(yīng)的 dom 結(jié)構(gòu) 代碼位置 :./src/vnode.ts 定義 vnode 類型 /** ...
摘要:元素從父節(jié)點(diǎn)刪除時(shí)觸發(fā),和略有不同,只影響到被移除節(jié)點(diǎn)中最頂層的節(jié)點(diǎn)在方法的最后調(diào)用,也就是完成后觸發(fā)源碼解析系列源碼解析一準(zhǔn)備工作源碼解析二函數(shù)源碼解析三對(duì)象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個(gè)人博客地址 文件路徑 : ./src/hooks.ts 這個(gè)文件主要是定義了 Virtual Dom 在實(shí)現(xiàn)過(guò)程中,在其執(zhí)行過(guò)程中的一系列鉤子。方便外部做一些處理 /...
閱讀 3428·2021-11-15 11:39
閱讀 1573·2021-09-22 10:02
閱讀 1319·2021-08-27 16:24
閱讀 3605·2019-08-30 15:52
閱讀 3418·2019-08-29 16:20
閱讀 832·2019-08-28 18:12
閱讀 559·2019-08-26 18:27
閱讀 726·2019-08-26 13:32