最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3中虛擬dom轉(zhuǎn)成真實(shí)dom的過程詳解

 更新時間:2024年09月10日 08:24:55   作者:zykk  
Vue.js?在其運(yùn)行過程中會將模板編譯成虛擬?DOM?(VNode),然后再將?VNode?渲染成實(shí)際的?DOM?節(jié)點(diǎn),這個過程是由?Vue?內(nèi)部的編譯器和渲染系統(tǒng)完成的,本文給大家介紹了Vue3中虛擬dom轉(zhuǎn)成真實(shí)dom的過程,需要的朋友可以參考下

前言

Vue.js 在其運(yùn)行過程中會將模板編譯成虛擬 DOM (VNode),然后再將 VNode 渲染成實(shí)際的 DOM 節(jié)點(diǎn)。這個過程是由 Vue 內(nèi)部的編譯器和渲染系統(tǒng)完成的.

雖然Vue 3 的虛擬 DOM 編譯過程對于開發(fā)者來說通常是透明的,但了解這些內(nèi)部機(jī)制有助于更好地理解和優(yōu)化應(yīng)用程序。

如果你對 Vue 3 的內(nèi)部實(shí)現(xiàn)感興趣,可以查閱 Vue 3 的官方文檔或閱讀 Vue 3 的源碼來深入了解這一過程。

Vue 3 中虛擬 DOM 的編譯過程

1. 模板編譯

在 Vue 3 中,模板編譯主要由兩個階段組成:解析和優(yōu)化。

  • 解析階段:Vue 3 的編譯器會將模板字符串解析成一個抽象語法樹 (Abstract Syntax Tree, AST),這個樹結(jié)構(gòu)表示了模板的結(jié)構(gòu)和內(nèi)容。編譯器會識別出模板中的各種指令(如 v-if, v-for, v-bind 等)并將它們轉(zhuǎn)換成對應(yīng)的 AST 節(jié)點(diǎn)。
  • 優(yōu)化階段:編譯器會對 AST 進(jìn)行優(yōu)化,以減少不必要的計(jì)算和 DOM 操作。例如,它可以提前計(jì)算靜態(tài)節(jié)點(diǎn),并將其標(biāo)記為靜態(tài)的,這樣在渲染時就不需要重新生成這些節(jié)點(diǎn)。

2. 生成渲染函數(shù)

一旦 AST 被創(chuàng)建并優(yōu)化后,編譯器會生成一個渲染函數(shù),這個函數(shù)可以用來創(chuàng)建虛擬 DOM 節(jié)點(diǎn)(VNode)。渲染函數(shù)通常會利用 Vue 內(nèi)置的 h 函數(shù)(createVNode 的別名)來創(chuàng)建 VNode。

3. 創(chuàng)建虛擬 DOM (VNode)

在 Vue 3 中,h 函數(shù)被用來創(chuàng)建 VNode。一個 VNode 是一個 JavaScript 對象,它包含了關(guān)于 DOM 節(jié)點(diǎn)的信息,如標(biāo)簽名、屬性、子節(jié)點(diǎn)等。例如:

const vnode = h(
  'div', // 標(biāo)簽名
  { id: 'app' }, // 屬性對象
  'Hello Vue 3!' // 子節(jié)點(diǎn)
);

4. 渲染到真實(shí) DOM

當(dāng) VNode 被創(chuàng)建后,Vue 會使用高效的算法來比較新舊 VNode,并更新真實(shí)的 DOM。這個過程稱為 patching。Vue 3 的 diff 算法旨在最小化 DOM 操作,從而提高性能。

今天來簡單介紹一下如何將一份虛擬dom轉(zhuǎn)成真實(shí)dom。

vdomToDom

虛擬dom結(jié)構(gòu)已有,掛載到root節(jié)點(diǎn)上,請問如何實(shí)現(xiàn)render函數(shù)?

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="root"></div>


    <script>
        const vnode = {
            tag: 'div',
            attrs: {
                id: 'app',
                class:'box'
            },
            children: [
                {
                    tag: 'span',
                    children: [{
                        tag: 'a',
                        children: [],
                    }],
                },
                {
                    tag: 'span',
                    children: [{
                        tag: 'a',
                        children: [],
                    }]
                }
            ]
        }


        render(vnode,document.getElementById('root'))

        function render(vnode, container) {
            
        }
    </script>
</body>

</html>

我們先來看一眼這份虛擬dom長什么樣。

首先最外層有個id為app類名為box的div,里面有兩個子節(jié)點(diǎn)span,第一個子節(jié)點(diǎn)中又有一個a,第二個子節(jié)點(diǎn)中也有一個a

那么vue中編譯dom的原理是什么,我們來一份簡易版看看。

首先我們就想有一個方法只要給一個虛擬dom就能生成dom,然后將其掛載到root上去,接下來就是如何實(shí)現(xiàn)createDom

function render(vnode, container) {
            const newDom = createDom(vnode)
            container.appendChild(newDom)
        }
function createDom(vnode) {
            const { tag, attrs, children } = vnode
            const dom = document.createElement(tag)
            if (typeof attrs === 'object' && attrs !== null) {
                updateProps(dom, {}, attrs) // 為dom添加屬性
            }
            if (children.length > 0) {
                reconcileChildren(children, dom) // 為dom添加子容器
            }
            return dom
        }

然后思考,如何為子容器添加屬性以及如何為容器添加子容器?

function updateProps(dom, oldProps = {}, newProps = {}) {
            for (const key in newProps) {
                if (key === 'style') {
                    let styleObj = newProps[key]
                    for (let attr in styleObj) {
                        dom.style[attr] = styleObj[attr]
                    }
                } else { // id / class
                    dom[key] = newProps[key]
                }
            }
        }

        function reconcileChildren(children, dom) {
            for (let child of children) {
                render(child, dom)
            }
        }

完整代碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="root"></div>


    <script>
        const vnode = {
            tag: 'div',
            attrs: {
                id: 'app',
                className: 'box'
            },
            children: [
                {
                    tag: 'span',
                    children: [{
                        tag: 'a',
                        children: [],
                    }],
                },
                {
                    tag: 'span',
                    children: [{
                        tag: 'a',
                        children: [],
                    }]
                }
            ]
        }


        render(vnode, document.getElementById('root'))

        function render(vnode, container) {
            const newDom = createDom(vnode)
            container.appendChild(newDom)
        }

        function createDom(vnode) {
            const { tag, attrs, children } = vnode
            const dom = document.createElement(tag)
            if (typeof attrs === 'object' && attrs !== null) {
                updateProps(dom, {}, attrs) // 為dom添加屬性
            }
            if (children.length > 0) {
                reconcileChildren(children, dom) // 為dom添加子容器
            }
            return dom
        }
        function updateProps(dom, oldProps = {}, newProps = {}) {
            for (const key in newProps) {
                if (key === 'style') {
                    let styleObj = newProps[key]
                    for (let attr in styleObj) {
                        dom.style[attr] = styleObj[attr]
                    }
                } else { // id / class
                    dom[key] = newProps[key]
                }
            }
        }

        function reconcileChildren(children, dom) {
            for (let child of children) {
                render(child, dom)
            }
        }
    </script>
</body>

</html>

效果

以上就是Vue3中虛擬dom轉(zhuǎn)成真實(shí)dom的過程詳解的詳細(xì)內(nèi)容,更多關(guān)于Vue3 虛擬dom轉(zhuǎn)成真實(shí)dom的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue元素實(shí)現(xiàn)動畫過渡效果

    vue元素實(shí)現(xiàn)動畫過渡效果

    這篇文章主要介紹了vue元素實(shí)現(xiàn)動畫過渡效果,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • vue?element表格某一列內(nèi)容過多,超出省略號顯示的實(shí)現(xiàn)

    vue?element表格某一列內(nèi)容過多,超出省略號顯示的實(shí)現(xiàn)

    這篇文章主要介紹了vue?element表格某一列內(nèi)容過多,超出省略號顯示的實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Vue3中使用this的詳細(xì)教程

    Vue3中使用this的詳細(xì)教程

    在vue3中新的組合式API中沒有this,那我們?nèi)绻枰玫絫his怎么辦?下面這篇文章主要給大家介紹了關(guān)于Vue3中使用this的詳細(xì)教程,需要的朋友可以參考下
    2023-07-07
  • 使用Vue.js中的過濾器實(shí)現(xiàn)冪方求值的方法

    使用Vue.js中的過濾器實(shí)現(xiàn)冪方求值的方法

    這篇文章主要介紹了使用Vue.js中的過濾器實(shí)現(xiàn)冪方求值的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Vant 在vue-cli 4.x中按需加載操作

    Vant 在vue-cli 4.x中按需加載操作

    這篇文章主要介紹了Vant 在vue-cli 4.x中按需加載操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue3中組件傳值的多種方法總結(jié)

    vue3中組件傳值的多種方法總結(jié)

    學(xué)習(xí)過vue2的寶子們肯定知道,組件傳值是vue項(xiàng)目開發(fā)過程中必不可少的功能場景,下面這篇文章主要給大家介紹了關(guān)于vue3中組件傳值的多種方法,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • vue項(xiàng)目中使用websocket的實(shí)現(xiàn)

    vue項(xiàng)目中使用websocket的實(shí)現(xiàn)

    本文主要介紹了vue項(xiàng)目中使用websocket的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • vue 圖標(biāo)選擇器的實(shí)例代碼

    vue 圖標(biāo)選擇器的實(shí)例代碼

    本文通過實(shí)例代碼給大家介紹了vue 圖標(biāo)選擇器的相關(guān)知識,圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-11-11
  • vue+echart實(shí)現(xiàn)雙柱狀圖

    vue+echart實(shí)現(xiàn)雙柱狀圖

    這篇文章主要為大家詳細(xì)介紹了vue+echart實(shí)現(xiàn)雙柱狀圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 在Vue.js中使用Mixins的方法

    在Vue.js中使用Mixins的方法

    本篇文章主要介紹了在Vue.js中使用Mixins的方法,Vue的Mixins是非常實(shí)用的編程方式,可以使代碼變得容易理解,有興趣的一起來了解一下
    2017-09-09

最新評論

天峻县| 德阳市| 井冈山市| 镇江市| 姚安县| 大港区| 南通市| 乐昌市| 托克逊县| 香港| 耿马| 沈丘县| 古交市| 乌拉特后旗| 德安县| 上蔡县| 大田县| 阿荣旗| 综艺| 祥云县| 广元市| 南澳县| 饶平县| 东兰县| 遂溪县| 台安县| 桃园县| 梅州市| 肃宁县| 喜德县| 舟山市| 沾益县| 建德市| 卓尼县| 台湾省| 项城市| 溧阳市| 黎平县| 通化市| 瓮安县| 右玉县|