摘要:模塊在里面,定義了一系列的模塊,這些模塊定義了相應的鉤子。主要接受兩個參數,。傳送門事件模塊待續。。。源碼解析系列源碼解析一準備工作源碼解析二函數源碼解析三對象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個人博客地址
模塊
在 ./src/modules 里面,定義了一系列的模塊 , 這些模塊定義了相應的鉤子 。這些鉤子會在 patch 的不同階段觸發,以完成相應模塊的功能處理
了解生命周期更多的內容,請查看 鉤子
主要的模塊有 :
attributes.ts
class.ts
dataset.ts
eventlisteners.ts
hero.ts
module.ts
props.ts
style.ts
其中 attributes class dataset props 四個比較簡單,都是定義了 create update 兩個鉤子,
eventlisteners hero style 這三個模塊就復雜一點。
另外 module.ts 只是定義了這些模塊所用到的一些鉤子
// 定義模塊的鉤子 export interface Module { pre: PreHook; create: CreateHook; update: UpdateHook; destroy: DestroyHook; remove: RemoveHook; post: PostHook; }
接下來我們來看看其他的模塊
attributes 模塊文件位置 : ./src/modules/attributes.ts
我們先拉到最后
// 創建以及更新的鉤子 export const attributesModule = { create: updateAttrs, update: updateAttrs } as Module; export default attributesModule;
attributesModule 導出了兩個方法, 都是調用了 updateAttrs 。
這個表示,在創建元素的時候,以及更新的時候,都會觸發這兩個鉤子,來更新 attribute。
updateAttrsupdateAttrs 主要接受兩個參數,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 開頭 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 兩個鉤子,統一由 updateClass 處理
這塊邏輯比較簡單 ,直接看代碼吧
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 都沒有 if (!oldClass && !klass) return; // 新老的 className 沒變 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 兩個鉤子,統一由 updateDataset 處理
這塊邏輯比較簡單 ,直接看代碼吧
const CAPS_REGEX = /[A-Z]/g; /** * 更新或創建 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 兩個鉤子,統一由 updateProps 處理
這塊邏輯比較簡單 ,直接看代碼吧
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 這一塊內容稍微多一點,故將其獨立出來一個章節。 傳送門 : 事件
style 模塊待續。。。
hero 模塊待續。。。
snabbdom源碼解析系列snabbdom源碼解析(一) 準備工作
snabbdom源碼解析(二) h函數
snabbdom源碼解析(三) vnode對象
snabbdom源碼解析(四) patch 方法
snabbdom源碼解析(五) 鉤子
snabbdom源碼解析(六) 模塊
snabbdom源碼解析(七) 事件處理
個人博客地址
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100419.html
摘要:閱讀源碼的時候,想了解虛擬結構的實現,發現在的地方。然而慢慢的人們發現,在我們的代碼中布滿了一系列操作的代碼。源碼解析系列源碼解析一準備工作源碼解析二函數源碼解析三對象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個人博客地址 前言 虛擬 DOM 結構概念隨著 react 的誕生而火起來,之后 vue2.0 也加入了虛擬 DOM 的概念。 閱讀 vue 源碼的時候,想了解...
摘要:這種解決方式也是相當優雅,值得學習源碼解析系列源碼解析一準備工作源碼解析二函數源碼解析三對象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個人博客地址 事件處理 我們在使用 vue 的時候,相信你一定也會對事件的處理比較感興趣。 我們通過 @click 的時候,到底是發生了什么呢! 雖然我們用 @click綁定在模板上,不過事件嚴格綁定在 vnode 上的 。 event...
介紹 這里是 typescript 的語法,定義了一系列的重載方法。h 函數主要根據傳進來的參數,返回一個 vnode 對象 代碼 代碼位置 : ./src/h.ts /** * 根據選擇器 ,數據 ,創建 vnode */ export function h(sel: string): VNode; export function h(sel: string, data: VNodeData...
摘要:對象是一個對象,用來表示相應的結構代碼位置定義類型定義類型選擇器數據,主要包括屬性樣式數據綁定時間等子節點關聯的原生節點文本唯一值,為了優化性能定義的類型定義綁定的數據類型屬性能直接用訪問的屬性樣式類樣式數據綁定的事件鉤子創建對象根據傳入的 vnode 對象 vnode 是一個對象,用來表示相應的 dom 結構 代碼位置 :./src/vnode.ts 定義 vnode 類型 /** ...
摘要:元素從父節點刪除時觸發,和略有不同,只影響到被移除節點中最頂層的節點在方法的最后調用,也就是完成后觸發源碼解析系列源碼解析一準備工作源碼解析二函數源碼解析三對象源碼解析四方法源碼解析五鉤子源碼解析六模塊源碼解析七事件處理個人博客地址 文件路徑 : ./src/hooks.ts 這個文件主要是定義了 Virtual Dom 在實現過程中,在其執行過程中的一系列鉤子。方便外部做一些處理 /...
閱讀 3419·2021-11-15 11:39
閱讀 1552·2021-09-22 10:02
閱讀 1309·2021-08-27 16:24
閱讀 3596·2019-08-30 15:52
閱讀 3412·2019-08-29 16:20
閱讀 824·2019-08-28 18:12
閱讀 550·2019-08-26 18:27
閱讀 715·2019-08-26 13:32