亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

從零開始,手寫一個(gè)簡(jiǎn)易的Virtual DOM

forrest23 / 1303人閱讀

摘要:本文為筆者通過實(shí)際操作,實(shí)現(xiàn)了一個(gè)非常簡(jiǎn)單的,加深對(duì)現(xiàn)今主流前端框架中的理解。用對(duì)象表示樹是用對(duì)象表示,并存儲(chǔ)在內(nèi)存中的。如果類型不一致,那么屬性一定是被更新的。如果有不相等的屬性,則認(rèn)為發(fā)生改變,需要處理的變化。

眾所周知,對(duì)前端而言,直接操作 DOM 是一件及其耗費(fèi)性能的事情,以 React 和 Vue 為代表的眾多框架普遍采用 Virtual DOM 來解決如今愈發(fā)復(fù)雜 Web 應(yīng)用中狀態(tài)頻繁發(fā)生變化導(dǎo)致的頻繁更新 DOM 的性能問題。本文為筆者通過實(shí)際操作,實(shí)現(xiàn)了一個(gè)非常簡(jiǎn)單的 Virtual DOM ,加深對(duì)現(xiàn)今主流前端框架中 Virtual DOM 的理解。

關(guān)于 Virtual DOM ,社區(qū)已經(jīng)有許多優(yōu)秀的文章,而本文是筆者采用自己的方式,并有所借鑒前輩們的實(shí)現(xiàn),以淺顯易懂的方式,對(duì) Virtual DOM 進(jìn)行簡(jiǎn)單實(shí)現(xiàn),但不包含snabbdom的源碼分析,在筆者的最終實(shí)現(xiàn)里,參考了snabbdom的原理,將本文的Virtual DOM實(shí)現(xiàn)進(jìn)行了改進(jìn),感興趣的讀者可以閱讀上面幾篇文章,并參考筆者本文的最終代碼進(jìn)行閱讀。

本文閱讀時(shí)間約15~20分鐘。

概述

本文分為以下幾個(gè)方面來講述極簡(jiǎn)版本的 Virtual DOM 核心實(shí)現(xiàn):

Virtual DOM 主要思想

用 JavaScript 對(duì)象表示 DOM 樹

將 Virtual DOM 轉(zhuǎn)換為真實(shí) DOM

設(shè)置節(jié)點(diǎn)的類型

設(shè)置節(jié)點(diǎn)的屬性

對(duì)子節(jié)點(diǎn)的處理

處理變化

新增與刪除節(jié)點(diǎn)

更新節(jié)點(diǎn)

更新子節(jié)點(diǎn)

Virtual DOM 主要思想

要理解 Virtual DOM 的含義,首先需要理解 DOM ,DOM 是針對(duì) HTML 文檔和 XML 文檔的一個(gè) API , DOM 描繪了一個(gè)層次化的節(jié)點(diǎn)樹,通過調(diào)用 DOM API,開發(fā)人員可以任意添加,移除和修改頁面的某一部分。而 Virtual DOM 則是用 JavaScript 對(duì)象來對(duì) Virtual DOM 進(jìn)行抽象化的描述。Virtual DOM 的本質(zhì)是JavaScript對(duì)象,通過 Render函數(shù),可以將 Virtual DOM 樹 映射為 真實(shí) DOM 樹。

一旦 Virtual DOM 發(fā)生改變,會(huì)生成新的 Virtual DOM ,相關(guān)算法會(huì)對(duì)比新舊兩顆 Virtual DOM 樹,并找到他們之間的不同,盡可能地通過最少的 DOM 操作來更新真實(shí) DOM 樹。

我們可以這么表示 Virtual DOM 與 DOM 的關(guān)系:DOM = Render(Virtual DOM)。

用 JavaScript 對(duì)象表示 DOM 樹

Virtual DOM 是用 JavaScript 對(duì)象表示,并存儲(chǔ)在內(nèi)存中的。主流的框架均支持使用 JSX 的寫法, JSX 最終會(huì)被 babel 編譯為JavaScript 對(duì)象,用于來表示Virtual DOM,思考下列的 JSX:

item

最終會(huì)被babel編譯為如下的 JavaScript對(duì)象:

{
    type: "div",
    props: null,
    children: [{
        type: "span",
        props: {
            class: "item",
        },
        children: ["item"],
    }, {
        type: "input",
        props: {
            disabled: true,
        },
        children: [],
    }],
}

我們可以注意到以下兩點(diǎn):

所有的 DOM 節(jié)點(diǎn)都是一個(gè)類似于這樣的對(duì)象:

{ type: "...", props: { ... }, children: { ... }, on: { ... } }

本文節(jié)點(diǎn)是用 JavaScript 字符串來表示

那么 JSX 又是如何轉(zhuǎn)化為 JavaScript 對(duì)象的呢。幸運(yùn)的是,社區(qū)有許許多多優(yōu)秀的工具幫助我們完成了這件事,由于篇幅有限,本文對(duì)這個(gè)問題暫時(shí)不做探討。為了方便大家更快速地理解 Virtual DOM ,對(duì)于這一個(gè)步驟,筆者使用了開源工具來完成。著名的 babel 插件babel-plugin-transform-react-jsx幫助我們完成這項(xiàng)工作。

為了更好地使用babel-plugin-transform-react-jsx,我們需要搭建一下webpack開發(fā)環(huán)境。具體過程這里不做闡述,有興趣自己實(shí)現(xiàn)的同學(xué)可以到simple-virtual-dom查看代碼。

對(duì)于不使用 JSX 語法的同學(xué),可以不配置babel-plugin-transform-react-jsx,通過我們的vdom函數(shù)創(chuàng)建 Virtual DOM:

function vdom(type, props, ...children) {
    return {
        type,
        props,
        children,
    };
}

然后我們可以通過如下代碼創(chuàng)建我們的 Virtual DOM 樹:

const vNode = vdom("div", null,
    vdom("span", { class: "item" }, "item"),
    vdom("input", { disabled: true })
);

在控制臺(tái)輸入上述代碼,可以看到,已經(jīng)創(chuàng)建好了用 JavaScript對(duì)象表示的 Virtual DOM 樹:

將 Virtual DOM 轉(zhuǎn)換為真實(shí) DOM

現(xiàn)在我們知道了如何用 JavaScript對(duì)象 來代表我們的真實(shí) DOM 樹,那么, Virtual DOM 又是怎么轉(zhuǎn)換為真實(shí) DOM 給我們呈現(xiàn)的呢?

在這之前,我們要先知道幾項(xiàng)注意事項(xiàng):

在代碼中,筆者將以$開頭的變量來表示真實(shí) DOM 對(duì)象;

toRealDom函數(shù)接受一個(gè) Virtual DOM 對(duì)象為參數(shù),將返回一個(gè)真實(shí) DOM 對(duì)象;

mount函數(shù)接受兩個(gè)參數(shù):將掛載 Virtual DOM 對(duì)象的父節(jié)點(diǎn),這是一個(gè)真實(shí) DOM 對(duì)象,命名為$parent;以及被掛載的 Virtual DOM 對(duì)象vNode

下面是toRealDom的函數(shù)原型:

function toRealDom(vNode) {
    let $dom;
    // do something with vNode
    return $dom;
}

通過toRealDom方法,我們可以將一個(gè)vNode對(duì)象轉(zhuǎn)化為一個(gè)真實(shí) DOM 對(duì)象,而mount函數(shù)通過appendChild,將真實(shí) DOM 掛載:

function mount($parent, vNode) {
    return $parent.appendChild(toRealDom(vNode));
}

下面,讓我們來分別處理vNodetype、propschildren

設(shè)置節(jié)點(diǎn)的類型

首先,因?yàn)槲覀兺瑫r(shí)具有字符類型的文本節(jié)點(diǎn)和對(duì)象類型的element節(jié)點(diǎn),需要對(duì)type做多帶帶的處理:

if (typeof vNode === "string") {
    $dom = document.createTextNode(vNode);
} else {
    $dom = document.createElement(vNode.type);
}

在這樣一個(gè)簡(jiǎn)單的toRealDom函數(shù)中,對(duì)type的處理就完成了,接下來讓我們看看對(duì)props的處理。

設(shè)置節(jié)點(diǎn)的屬性

我們知道,如果節(jié)點(diǎn)有props,那么props是一個(gè)對(duì)象。通過遍歷props,調(diào)用setProp方法,對(duì)每一類props多帶帶處理。

if (vNode.props) {
    Object.keys(vNode.props).forEach(key => {
        setProp($dom, key, vNode.props[key]);
    });
}

setProp接受三個(gè)參數(shù):

$target,這是一個(gè)真實(shí) DOM 對(duì)象,setProp將對(duì)這個(gè)節(jié)點(diǎn)進(jìn)行 DOM 操作;

name,表示屬性名;

value,表示屬性的值;

讀到這里,相信你已經(jīng)大概清楚setProp需要做什么了,一般情況下,對(duì)于普通的props,我們會(huì)通過setAttribute給 DOM 對(duì)象附加屬性。

function setProp($target, name, value) {
    return $target.setAttribute(name, value);
}

但這遠(yuǎn)遠(yuǎn)不夠,思考下列的 JSX 結(jié)構(gòu):

console.log("item")}>item

從上面的 JSX 結(jié)構(gòu)中,我們發(fā)現(xiàn)以下幾點(diǎn):

由于class是 JavaScript 的保留字, JSX 一般使用className來表示 DOM 節(jié)點(diǎn)所屬的class

一般以on開頭的屬性來表示事件;

除字符類型外,屬性還可能是布爾值,如disabled,當(dāng)該值為true時(shí),則添加這一屬性;

所以,setProp也同樣需要考慮上述情況:

function isEventProp(name) {
    return /^on/.test(name);
}

function extractEventName(name) {
    return name.slice(2).toLowerCase();
}

function setProp($target, name, value) {
    if (name === "className") { // 因?yàn)閏lass是保留字,JSX使用className來表示節(jié)點(diǎn)的class
        return $target.setAttribute("class", value);
    } else if (isEventProp(name)) { // 針對(duì) on 開頭的屬性,為事件
        return $target.addEventListener(extractEventName(name), value);
    } else if (typeof value === "boolean") { // 兼容屬性為布爾值的情況
        if (value) {
            $target.setAttribute(name, value);
        }
        return $target[name] = value;
    } else {
        return $target.setAttribute(name, value);
    }
}

最后,還有一類屬性是我們的自定義屬性,例如主流框架中的組件間的狀態(tài)傳遞,即通過props來進(jìn)行傳遞的,我們并不希望這一類屬性顯示在 DOM 中,因此需要編寫一個(gè)函數(shù)isCustomProp來檢查這個(gè)屬性是否是自定義屬性,因?yàn)楸疚闹皇菫榱藢?shí)現(xiàn) Virtual DOM 的核心思想,為了方便,在本文中,這個(gè)函數(shù)直接返回false。

function isCustomProp(name) {
    return false;
}

最終的setProp函數(shù):

function setProp($target, name, value) {
    if (isCustomProp(name)) {
        return;
    } else if (name === "className") { // fix react className
        return $target.setAttribute("class", value);
    } else if (isEventProp(name)) {
        return $target.addEventListener(extractEventName(name), value);
    } else if (typeof value === "boolean") {
        if (value) {
            $target.setAttribute(name, value);
        }
        return $target[name] = value;
    } else {
        return $target.setAttribute(name, value);
    }
}
對(duì)子節(jié)點(diǎn)的處理

對(duì)于children里的每一項(xiàng),都是一個(gè)vNode對(duì)象,在進(jìn)行 Virtual DOM 轉(zhuǎn)化為真實(shí) DOM 時(shí),子節(jié)點(diǎn)也需要被遞歸轉(zhuǎn)化,可以想到,針對(duì)有子節(jié)點(diǎn)的情況,需要對(duì)子節(jié)點(diǎn)以此遞歸調(diào)用toRealDom,如下代碼所示:

if (vNode.children && vNode.children.length) {
    vNode.children.forEach(childVdom => {
        const realChildDom = toRealDom(childVdom);
        $dom.appendChild(realChildDom);
    });
}

最終完成的toRealDom如下:

function toRealDom(vNode) {
    let $dom;
    if (typeof vNode === "string") {
        $dom = document.createTextNode(vNode);
    } else {
        $dom = document.createElement(vNode.type);
    }

    if (vNode.props) {
        Object.keys(vNode.props).forEach(key => {
            setProp($dom, key, vNode.props[key]);
        });
    }

    if (vNode.children && vNode.children.length) {
        vNode.children.forEach(childVdom => {
            const realChildDom = toRealDom(childVdom);
            $dom.appendChild(realChildDom);
        });
    }

    return $dom;
}
處理變化

Virtual DOM 之所以被創(chuàng)造出來,最根本的原因是性能提升,通過 Virtual DOM ,開發(fā)者可以減少許多不必要的 DOM 操作,以達(dá)到最優(yōu)性能,那么下面我們來看看 Virtual DOM 算法 是如何通過對(duì)比更新前的 Virtual DOM 樹和更新后的 Virtual DOM 樹來實(shí)現(xiàn)性能優(yōu)化的。

注:本文是筆者的最簡(jiǎn)單實(shí)現(xiàn),目前社區(qū)普遍通用的算法是snabbdom,如 Vue 則是借鑒該算法實(shí)現(xiàn)的 Virtual DOM ,有興趣的讀者可以查看這個(gè)庫的源代碼,基于本文的 Virtual DOM 的小示例,筆者最終也參考了該算法實(shí)現(xiàn),本文demo傳送門,由于篇幅有限,感興趣的讀者可以自行研究。

為了處理變化,首先聲明一個(gè)updateDom函數(shù),這個(gè)函數(shù)接受以下四個(gè)參數(shù):

$parent,表示將被掛載的父節(jié)點(diǎn);

oldVNode,舊的VNode對(duì)象;

newVNode,新的VNode對(duì)象;

index,在更新子節(jié)點(diǎn)時(shí)使用,表示當(dāng)前更新第幾個(gè)子節(jié)點(diǎn),默認(rèn)為0;

函數(shù)原型如下:

function updateDom($parent, oldVNode, newVNode, index = 0) {

}
新增與刪除節(jié)點(diǎn)

首先我們來看新增一個(gè)節(jié)點(diǎn)的情況,對(duì)于原本沒有該節(jié)點(diǎn),需要添加新的一個(gè)節(jié)點(diǎn)到 DOM 樹中,我們需要通過appendChild來實(shí)現(xiàn):

轉(zhuǎn)化為代碼表述為:

// 沒有舊的節(jié)點(diǎn),添加新的節(jié)點(diǎn)
if (!oldVNode) {
    return $parent.appendChild(toRealDom(newVNode));
}

同理,對(duì)于刪除一個(gè)舊節(jié)點(diǎn)的情況,我們通過removeChild來實(shí)現(xiàn),在這里,我們應(yīng)該從真實(shí) DOM 中將舊的節(jié)點(diǎn)刪掉,但問題是在這個(gè)函數(shù)中是直接取不到這一個(gè)節(jié)點(diǎn)的,我們需要知道這個(gè)節(jié)點(diǎn)在父節(jié)點(diǎn)中的位置,事實(shí)上,可以通過$parent.childNodes[index]來取到,這便是上面提到的為何需要傳入index,它表示當(dāng)前更新的節(jié)點(diǎn)在父節(jié)點(diǎn)中的索引:

轉(zhuǎn)化為代碼表述為:

const $currentDom = $parent.childNodes[index];

// 沒有新的節(jié)點(diǎn),刪除舊的節(jié)點(diǎn)
if (!newVNode) {
    return $parent.removeChild($currentDom);
}
更新節(jié)點(diǎn)

Virtual DOM 的核心在于如何高效更新節(jié)點(diǎn),下面我們來看看更新節(jié)點(diǎn)的情況。

首先,針對(duì)文本節(jié)點(diǎn),我們可以簡(jiǎn)單處理,對(duì)于文本節(jié)點(diǎn)是否發(fā)生改變,只需要通過比較其新舊字符串是否相等即可,如果是相同的文本節(jié)點(diǎn),是不需要我們更新 DOM 的,在updateDom函數(shù)中,直接return即可:

// 都是文本節(jié)點(diǎn),都沒有發(fā)生變化
if (typeof oldVNode === "string" && typeof newVNode === "string" && oldVNode === newVNode) {
    return;
}

接下來,考慮節(jié)點(diǎn)是否真的需要更新,如圖所示,一個(gè)節(jié)點(diǎn)的類型從span換成了div,顯而易見,這是一定需要我們?nèi)ジ?b>DOM的:

我們需要編寫一個(gè)函數(shù)isNodeChanged來幫助我們判斷舊節(jié)點(diǎn)和新節(jié)點(diǎn)是否真的一致,如果不一致,需要我們把節(jié)點(diǎn)進(jìn)行替換:

function isNodeChanged(oldVNode, newVNode) {
    // 一個(gè)是textNode,一個(gè)是element,一定改變
    if (typeof oldVNode !== typeof newVNode) {
        return true;
    }

    // 都是textNode,比較文本是否改變
    if (typeof oldVNode === "string" && typeof newVNode === "string") {
        return oldVNode !== newVNode;
    }

    // 都是element節(jié)點(diǎn),比較節(jié)點(diǎn)類型是否改變
    if (typeof oldVNode === "object" && typeof newVNode === "object") {
        return oldVNode.type !== newVNode.type;
    }
}

updateDom中,發(fā)現(xiàn)節(jié)點(diǎn)類型發(fā)生變化,則將該節(jié)點(diǎn)直接替換,如下代碼所示,通過調(diào)用replaceChild,將舊的 DOM 節(jié)點(diǎn)移除,并將新的 DOM 節(jié)點(diǎn)加入:

if (isNodeChanged(oldVNode, newVNode)) {
    return $parent.replaceChild(toRealDom(newVNode), $currentDom);
}

但這遠(yuǎn)遠(yuǎn)還沒有結(jié)束,考慮下面這種情況:



對(duì)比上面的新舊兩個(gè)節(jié)點(diǎn),發(fā)現(xiàn)節(jié)點(diǎn)類型并沒有發(fā)生改變,即VNode.type都是"div",但是節(jié)點(diǎn)的屬性卻發(fā)生了改變,除了針對(duì)節(jié)點(diǎn)類型的變化更新 DOM 外,針對(duì)節(jié)點(diǎn)的屬性的改變,也需要對(duì)應(yīng)把 DOM 更新。

與上述方法類似,我們編寫一個(gè)isPropsChanged函數(shù),來判斷新舊兩個(gè)節(jié)點(diǎn)的屬性是否有發(fā)生變化:

function isPropsChanged(oldProps, newProps) {
    // 類型都不一致,props肯定發(fā)生變化了
    if (typeof oldProps !== typeof newProps) {
        return true;
    }

    // props為對(duì)象
    if (typeof oldProps === "object" && typeof newProps === "object") {
        const oldKeys = Object.keys(oldProps);
        const newkeys = Object.keys(newProps);
        // props的個(gè)數(shù)都不一樣,一定發(fā)生了變化
        if (oldKeys.length !== newkeys.length) {
            return true;
        }
        // props的個(gè)數(shù)相同的情況,遍歷props,看是否有不一致的props
        for (let i = 0; i < oldKeys.length; i++) {
            const key = oldKeys[i]
            if (oldProps[key] !== newProps[key]) {
                return true;
            }
        }
        // 默認(rèn)未改變
        return false;
    }

    return false;
}

因?yàn)楫?dāng)節(jié)點(diǎn)沒有任何屬性時(shí),propsnull,isPropsChanged首先判斷新舊兩個(gè)節(jié)點(diǎn)的props是否是同一類型,即是否存在舊節(jié)點(diǎn)的propsnull,新節(jié)點(diǎn)有新的屬性,或者反之:新節(jié)點(diǎn)的propsnull,舊節(jié)點(diǎn)的屬性被刪除了。如果類型不一致,那么屬性一定是被更新的。

接下來,考慮到節(jié)點(diǎn)在更新前后都有props的情況,我們需要判斷更新前后的props是否一致,即兩個(gè)對(duì)象是否全等,遍歷即可。如果有不相等的屬性,則認(rèn)為props發(fā)生改變,需要處理props的變化。

現(xiàn)在,讓我們回到我們的updateDom函數(shù),看看是把Virtual DOM 節(jié)點(diǎn)props的更新應(yīng)用到真實(shí) DOM 上的。

// 虛擬DOM的type未改變,對(duì)比節(jié)點(diǎn)的props是否改變
const oldProps = oldVNode.props || {};
const newProps = newVNode.props || {};
if (isPropsChanged(oldProps, newProps)) {
    const oldPropsKeys = Object.keys(oldProps);
    const newPropsKeys = Object.keys(newProps);

    // 如果新節(jié)點(diǎn)沒有屬性,把舊的節(jié)點(diǎn)的屬性清除掉
    if (newPropsKeys.length === 0) {
        oldPropsKeys.forEach(propKey => {
            removeProp($currentDom, propKey, oldProps[propKey]);
        });
    } else {
        // 拿到所有的props,以此遍歷,增加/刪除/修改對(duì)應(yīng)屬性
        const allPropsKeys = new Set([...oldPropsKeys, ... newPropsKeys]);
        allPropsKeys.forEach(propKey => {
            // 屬性被去除了
            if (!newProps[propKey]) {
                return removeProp($currentDom, propKey, oldProps[propKey]);
            }
            // 屬性改變了/增加了
            if (newProps[propKey] !== oldProps[propKey]) {
                return setProp($currentDom, propKey, newProps[propKey]);
            }
        });
    }
}

上面的代碼也非常好理解,如果發(fā)現(xiàn)props改變了,那么對(duì)舊的props的每項(xiàng)去做遍歷。把不存在的屬性清除,再把新增加的屬性加入到更新后的 DOM 樹中:

首先,如果新的節(jié)點(diǎn)沒有屬性,遍歷刪除所有舊的節(jié)點(diǎn)的屬性,在這里,我們通過調(diào)用removeProp刪除。removePropsetProp相對(duì)應(yīng),由于本文篇幅有限,筆者在這里就不做過多闡述;

function removeProp($target, name, value) {
    if (isCustomProp(name)) {
        return;
    } else if (name === "className") { // fix react className
        return $target.removeAttribute("class");
    } else if (isEventProp(name)) {
        return $target.removeEventListener(extractEventName(name), value);
    } else if (typeof value === "boolean") {
        $target.removeAttribute(name);
        $target[name] = false;
    } else {
        $target.removeAttribute(name);
    }
}

如果新節(jié)點(diǎn)有屬性,那么拿到舊節(jié)點(diǎn)和新節(jié)點(diǎn)所有屬性,遍歷新舊節(jié)點(diǎn)的所有屬性,如果屬性在新節(jié)點(diǎn)中沒有,那么說明該屬性被刪除了。如果新的節(jié)點(diǎn)與舊的節(jié)點(diǎn)屬性不一致/或者是新增的屬性,則調(diào)用setProp給真實(shí) DOM 節(jié)點(diǎn)添加新的屬性。

更新子節(jié)點(diǎn)

在最后,與toRealDom類似的是,在updateDom中,我們也應(yīng)當(dāng)處理所有子節(jié)點(diǎn),對(duì)子節(jié)點(diǎn)進(jìn)行遞歸調(diào)用updateDom,一個(gè)一個(gè)對(duì)比所有子節(jié)點(diǎn)的VNode是否有更新,一旦VNode有更新,則真實(shí) DOM 也需要重新渲染:

// 根節(jié)點(diǎn)相同,但子節(jié)點(diǎn)不同,要遞歸對(duì)比子節(jié)點(diǎn)
if (
    (oldNode.children && oldNode.children.length) ||
    (newNode.children && newNode.children.length)
) {
    for (let i = 0; i < oldNode.children.length || i < newNode.children.length; i++) {
        updateDom($currentDom, oldNode.children[i], newNode.children[i], i);
    }
}
遠(yuǎn)遠(yuǎn)沒有結(jié)束

以上是筆者實(shí)現(xiàn)的最簡(jiǎn)單的 Virtual DOM 代碼,但這與社區(qū)我們所用到 Virtual DOM 算法是有天壤之別的,筆者在這里舉個(gè)最簡(jiǎn)單的例子:


  • 1
  • 2
  • 3
  • 4
  • 5

  • 5
  • 1
  • 2
  • 3
  • 4

對(duì)于上述代碼中實(shí)現(xiàn)的updateDom函數(shù)而言,更新前后的 DOM 結(jié)構(gòu)如上所示,則會(huì)觸發(fā)五個(gè)li節(jié)點(diǎn)全部重新渲染,這顯然是一種性能的浪費(fèi)。而snabbdom則通過移動(dòng)節(jié)點(diǎn)的方式較好地解決了上述問題,由于本文篇幅有限,并且社區(qū)也有許多對(duì)該 Virtual DOM 算法的分析文章,筆者就不在本文做過多闡述了,有興趣的讀者可以到自行研究。筆者也基于本文實(shí)例,參考snabbdom算法實(shí)現(xiàn)了最終的版本,有興趣的讀者可以查看本文示例最終版

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/104537.html

相關(guān)文章

  • 【React進(jìn)階系列】從零開始手把手教你實(shí)現(xiàn)一個(gè)Virtual DOM(一)

    摘要:可實(shí)際上并不是創(chuàng)造的,將這個(gè)概念拿過來以后融會(huì)貫通慢慢地成為目前前端最炙手可熱的框架之一。則是將再抽象一層生成的簡(jiǎn)化版對(duì)象,這個(gè)對(duì)象也擁有上的一些屬性,比如等,但它是完全脫離于瀏覽器而存在的。所以今天我要手把手教大家怎么從零開始實(shí)現(xiàn)。 假如你的項(xiàng)目使用了React,你知道怎么做性能優(yōu)化嗎?你知道為什么React讓你寫shouldComponentUpdate或者React.PureCo...

    PumpkinDylan 評(píng)論0 收藏0
  • 【React進(jìn)階系列】從零開始手把手教你實(shí)現(xiàn)一個(gè)Virtual DOM(二)

    摘要:上集回顧從零開始手把手教你實(shí)現(xiàn)一個(gè)一上一集我們介紹了什么是,為什么要用,以及我們要怎樣來實(shí)現(xiàn)一個(gè)。完成后,在命令行中輸入安裝下依賴。最后返回這個(gè)目標(biāo)節(jié)點(diǎn)。明天,我們迎接挑戰(zhàn),開始處理數(shù)據(jù)變動(dòng)引起的重新渲染,我們要如何新舊,生成補(bǔ)丁,修改。 上集回顧 從零開始手把手教你實(shí)現(xiàn)一個(gè)Virtual DOM(一)上一集我們介紹了什么是VDOM,為什么要用VDOM,以及我們要怎樣來實(shí)現(xiàn)一個(gè)VDOM...

    dendoink 評(píng)論0 收藏0
  • javascript知識(shí)點(diǎn)

    摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長(zhǎng)后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會(huì)討論安全的類型檢測(cè)惰性載入函數(shù)凍結(jié)對(duì)象定時(shí)器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對(duì)寫代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...

    Karrdy 評(píng)論0 收藏0
  • 【React進(jìn)階系列】從零開始手把手教你實(shí)現(xiàn)一個(gè)Virtual DOM(三)

    摘要:函數(shù)依次做了這幾件事調(diào)用函數(shù),對(duì)比新舊兩個(gè),根據(jù)兩者的不同得到需要修改的補(bǔ)丁將補(bǔ)丁到真實(shí)上當(dāng)計(jì)數(shù)器小于等于的時(shí)候,將加,再繼續(xù)下一次當(dāng)計(jì)數(shù)器大于的時(shí)候,結(jié)束下面我們來實(shí)現(xiàn)函數(shù)和函數(shù)。 上集回顧 【React進(jìn)階系列】從零開始手把手教你實(shí)現(xiàn)一個(gè)Virtual DOM(二) 上集我們實(shí)現(xiàn)了首次渲染從JSX=>Hyperscript=>VDOM=>DOM的過程,今天我們來看一下當(dāng)數(shù)據(jù)變動(dòng)的時(shí)...

    qqlcbb 評(píng)論0 收藏0
  • vue源碼閱讀之?dāng)?shù)據(jù)渲染過程

    摘要:圖在中應(yīng)用三數(shù)據(jù)渲染過程數(shù)據(jù)綁定實(shí)現(xiàn)邏輯本節(jié)正式分析從到數(shù)據(jù)渲染到頁面的過程,在中定義了一個(gè)的構(gòu)造函數(shù)。一、概述 vue已是目前國(guó)內(nèi)前端web端三分天下之一,也是工作中主要技術(shù)棧之一。在日常使用中知其然也好奇著所以然,因此嘗試閱讀vue源碼并進(jìn)行總結(jié)。本文旨在梳理初始化頁面時(shí)data中的數(shù)據(jù)是如何渲染到頁面上的。本文將帶著這個(gè)疑問一點(diǎn)點(diǎn)追究vue的思路??傮w來說vue模版渲染大致流程如圖1所...

    AlphaGooo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<