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

Vue手寫(xiě)實(shí)現(xiàn)組件初渲染

 更新時(shí)間:2022年08月15日 10:40:40   作者:夏日  
這篇文章主要介紹了Vue手寫(xiě)實(shí)現(xiàn)組件初渲染,在Vue進(jìn)行文本編譯之后,會(huì)得到代碼字符串生成的render函數(shù),本文會(huì)基于render函數(shù)展開(kāi)主題相關(guān)內(nèi)容,感興趣的朋友可以參考一下

前言

Vue進(jìn)行文本編譯之后,會(huì)得到代碼字符串生成的render函數(shù)。本文會(huì)基于render函數(shù)介紹以下內(nèi)容:

  • 執(zhí)行render函數(shù)生成虛擬節(jié)點(diǎn)
  • 通過(guò)vm._update方法,將虛擬節(jié)點(diǎn)渲染為真實(shí)DOM

vm.$mount方法中,文本編譯完成后,要進(jìn)行組件的掛載,代碼如下:

Vue.prototype.$mount = function (el) {
  // text compile code ....
  mountComponent(vm);
};

// src/lifecycle.js
export function mountComponent (vm) {
  vm._update(vm._render());
}

下面詳細(xì)介紹vm._render()vm._update()中到底做了什么

生成虛擬節(jié)點(diǎn)

原生DOM節(jié)點(diǎn)擁有大量的屬性和方法,操作DOM比較耗費(fèi)性能。在Vue中通過(guò)一個(gè)對(duì)象來(lái)描述DOM中的節(jié)點(diǎn),這個(gè)對(duì)象就是虛擬節(jié)點(diǎn),Vue組件樹(shù)構(gòu)建的整個(gè)虛擬節(jié)點(diǎn)樹(shù)就是虛擬DOM。

這是一段html

<div id="app">
  <span>hello world {{name}}</span>
</div>
<script>
  new Vue({
    el: '#app',
    data () {
      return {
        name: 'zs'
      }
    }
  })
</script>

其對(duì)應(yīng)的虛擬節(jié)點(diǎn)如下:

const vNode = {
  tag: 'div',
  props: { id: 'app' },
  key: undefined,
  children: [
    {
      tag: 'span',
      props: {},
      key: undefined,
      children: undefined,
      text: 'helloworldzs'
    }
  ],
  text: undefined
}

Vue.prototype._render函數(shù)中,通過(guò)執(zhí)行文本編譯后生成的render方法,會(huì)得到虛擬節(jié)點(diǎn):

// src/vdom/index.js
Vue.prototype._render = function () {
  const vm = this;
  // 執(zhí)行選項(xiàng)中的render方法,指定this為Vue實(shí)例
  const { render } = vm.$options;
  return render.call(vm);
};

render函數(shù)中用到了_c,_v,_s這些方法,需要在Vue.prototype上添加這些方法,在render函數(shù)內(nèi)就可以通過(guò)實(shí)例調(diào)用它們:

// 創(chuàng)建虛擬節(jié)點(diǎn)
function vNode (tag, props, key, children, text) {
  return {
    tag,
    props,
    key,
    children,
    text
  };
}

// 創(chuàng)建虛擬元素節(jié)點(diǎn)
function createVElement (tag, props = {}, ...children) {
  const { key } = props;
  delete props.key;
  return vNode(tag, props, key, children);
}

// 創(chuàng)建虛擬文本節(jié)點(diǎn)
function createTextVNode (text) {
  return vNode(undefined, undefined, undefined, undefined, text);
}

// 將實(shí)例中data里的值轉(zhuǎn)換為字符串
function stringify (value) {
  if (value == null) {
    return '';
  } else if (typeof value === 'object') {
    return JSON.stringify(value);
  } else {
    return value;
  }
}

export function renderMixin (Vue) {
  Vue.prototype._c = createVElement;
  Vue.prototype._v = createTextVNode;
  Vue.prototype._s = stringify;
  // some code ...  
}

_render函數(shù)最終會(huì)遞歸的調(diào)用這些函數(shù)來(lái)得到虛擬節(jié)點(diǎn),并將其返回:

const vNode = vm.createVElement('div', { id: 'app' },
  vm.createVElement('span', undefined,
    vm.createTextVNode('hello') + vm.createTextVNode('world') + vm.stringify(vm.name)
  )
)

在生成虛擬節(jié)點(diǎn)的過(guò)程中,會(huì)從組件實(shí)例vm中取值,從而觸發(fā)對(duì)應(yīng)屬性的get/set方法。

將虛擬節(jié)點(diǎn)處理為真實(shí)節(jié)點(diǎn)

在通過(guò)Vue.prototype._render函數(shù)生成虛擬節(jié)點(diǎn)后,在Vue.prototype._update方法中會(huì)利用虛擬節(jié)點(diǎn),替換當(dāng)前頁(yè)面上渲染的元素app。

其代碼如下:

// src/lifecycle.js
export function lifecycleMixin (Vue) {
  Vue.prototype._update = function (vNode) {
    const vm = this;
    patch(vm.$el, vNode);
  };
}

patch方法中,會(huì)通過(guò)虛擬節(jié)點(diǎn)創(chuàng)建真實(shí)節(jié)點(diǎn),并將真實(shí)節(jié)點(diǎn)插入頁(yè)面中:

// src/vdom/patch.js
export function patch (oldVNode, vNode) {
  // 將虛擬節(jié)點(diǎn)創(chuàng)建為真實(shí)節(jié)點(diǎn),并插入到dom中
  const el = createElement(vNode);
  // 獲取到老節(jié)點(diǎn)的父節(jié)點(diǎn)
  const parentNode = oldVNode.parentNode;
  // 將新節(jié)點(diǎn)插入到老節(jié)點(diǎn)之后
  parentNode.insertBefore(el, oldVNode.nextSibling);
  // 刪除老節(jié)點(diǎn)
  parentNode.removeChild(oldVNode);
}

createElement中是用虛擬節(jié)點(diǎn)生成真實(shí)節(jié)點(diǎn)的邏輯:

  • 通過(guò)document.createElement來(lái)創(chuàng)建元素節(jié)點(diǎn)
  • 元素節(jié)點(diǎn)通過(guò)updateProperties方法來(lái)設(shè)置它的屬性
  • 通過(guò)document.createTextNode來(lái)創(chuàng)建文本節(jié)點(diǎn)
function createElement (vNode) {
  if (typeof vNode.tag === 'string') {
    vNode.el = document.createElement(vNode.tag);
    updateProperties(vNode);
    for (let i = 0; i < vNode.children.length; i++) {
      const child = vNode.children[i];
      vNode.el.appendChild(createElement(child));
    }
  } else {
    vNode.el = document.createTextNode(vNode.text);
  }
  return vNode.el;
}

createElement會(huì)生成的真實(shí)DOM元素el并返回,內(nèi)部會(huì)對(duì)子虛擬節(jié)點(diǎn)再次調(diào)用createElement來(lái)繼續(xù)生成真實(shí)元素,然后將生成的真實(shí)元素通過(guò)appendChild方法插入到父節(jié)點(diǎn)中。

執(zhí)行createElement最后得到的el是將所有子節(jié)點(diǎn)都插入到內(nèi)部的元素,但其實(shí)el此時(shí)還是脫離真實(shí)DOM存在的,最后將它插入到真實(shí)DOM中便完成了整個(gè)真實(shí)節(jié)點(diǎn)的渲染。

下面是其執(zhí)行邏輯示意圖:

總結(jié)

Vue的組件掛載vm.$mount(el)過(guò)程如下:

  • template編譯為render函數(shù)
  • 使用render函數(shù)生成虛擬節(jié)點(diǎn),函數(shù)中需要的變量和方法會(huì)去vm的自身和原型鏈中查找
  • 將虛擬節(jié)點(diǎn)創(chuàng)建為真實(shí)節(jié)點(diǎn),并遞歸的插入到頁(yè)面中
  • 使用真實(shí)節(jié)點(diǎn)替換之前老的節(jié)點(diǎn)

到目前為止,我們已經(jīng)實(shí)現(xiàn)了Vue組件初渲染的整個(gè)過(guò)程,下面用一張圖來(lái)總結(jié)一下:

到此這篇關(guān)于Vue手寫(xiě)實(shí)現(xiàn)組件初渲染的文章就介紹到這了,更多相關(guān)Vue組件初渲染內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

源碼地址: 傳送門

相關(guān)文章

  • vue項(xiàng)目中js文件使用vue的this實(shí)例說(shuō)明

    vue項(xiàng)目中js文件使用vue的this實(shí)例說(shuō)明

    這篇文章主要介紹了vue項(xiàng)目中js文件使用vue的this實(shí)例說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • vue3使用echart的兩種引入方式以及注意事項(xiàng)說(shuō)明

    vue3使用echart的兩種引入方式以及注意事項(xiàng)說(shuō)明

    這篇文章主要介紹了vue3使用echart的兩種引入方式以及注意事項(xiàng)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 超簡(jiǎn)單易懂的vue組件傳值

    超簡(jiǎn)單易懂的vue組件傳值

    這篇文章主要為大家詳細(xì)介紹了vue組件傳值,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • vue2項(xiàng)目增加eslint配置代碼規(guī)范示例

    vue2項(xiàng)目增加eslint配置代碼規(guī)范示例

    這篇文章主要為大家介紹了vue2項(xiàng)目增加eslint配置代碼規(guī)范示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • vue中虛擬DOM與Diff算法知識(shí)精講

    vue中虛擬DOM與Diff算法知識(shí)精講

    這篇文章主要為大家介紹了vue中虛擬DOM與Diff算法知識(shí)的圖文精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • 使用Vue手寫(xiě)一個(gè)對(duì)話框

    使用Vue手寫(xiě)一個(gè)對(duì)話框

    相信大家之前都寫(xiě)過(guò)一些組件,尤其是這樣的彈窗組件,這篇文章主要來(lái)和大家聊聊如何使用Vue手寫(xiě)一個(gè)對(duì)話框,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04
  • Vue記事本實(shí)例詳解

    Vue記事本實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)記事本功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • vue調(diào)試工具vue-devtools的安裝全過(guò)程

    vue調(diào)試工具vue-devtools的安裝全過(guò)程

    這篇文章主要介紹了vue調(diào)試工具vue-devtools的安裝全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Vue中通過(guò)vue-router實(shí)現(xiàn)命名視圖的問(wèn)題

    Vue中通過(guò)vue-router實(shí)現(xiàn)命名視圖的問(wèn)題

    這篇文章主要介紹了在Vue中通過(guò)vue-router實(shí)現(xiàn)命名視圖,本文給大家提到了vue-router的原理解析,給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Vue項(xiàng)目打包編譯優(yōu)化方案

    Vue項(xiàng)目打包編譯優(yōu)化方案

    當(dāng)一個(gè)較復(fù)雜的vue項(xiàng)目打包后,文件會(huì)非常大,而且訪問(wèn)時(shí)資源加載速度很慢,本文介紹了幾種措施來(lái)優(yōu)化。
    2020-09-09

最新評(píng)論

峨边| 康定县| 湖南省| 北宁市| 兴仁县| 承德县| 祁门县| 阳朔县| 乐都县| 呼图壁县| 安徽省| 高阳县| 遵化市| 阿拉尔市| 博野县| 连平县| 含山县| 裕民县| 罗源县| 旬阳县| 崇义县| 山阳县| 龙泉市| 分宜县| 甘谷县| 马山县| 香港| 琼结县| 沾益县| 扎鲁特旗| 开原市| 绥中县| 柳林县| 玛多县| 胶南市| 华坪县| 黄骅市| 凤阳县| 孟津县| 丰都县| 金山区|