欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3渲染器與編譯器深入淺析

 更新時間:2023年02月01日 15:02:39   作者:FE雜志社  
這篇文章主要為大家介紹了Vue3渲染器與編譯器深入淺析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

渲染器

相關(guān)概念

渲染器是Vue框架性能的核心,Vue3的渲染器不僅包含傳統(tǒng)的Diff算法,還獨創(chuàng)了快捷的路徑更新方式,可以充分利用渲染器提供的信息,大大提升更新和渲染的性能;

  • Vue中的h函數(shù)返回的就是一個對象,其作用是讓編寫的虛擬DOM變得更加輕松,換句話說h函數(shù)就是一個輔助創(chuàng)建虛擬DOM的工具函數(shù)而已;
  • 虛擬DOM就是用來描述真實DOM的普通JS對象,渲染器會將該對象渲染成真實DOM元素,當(dāng)然虛擬DOM也可以描述組件信息,而組件又可以理解成為一組DOM元素的封裝
  • 組件的渲染函數(shù):一個組件要渲染的內(nèi)容是通過渲染函數(shù)來描述的,也就是Vue中的render函數(shù),Vue會根據(jù)組件的render函數(shù)的返回值拿到虛擬DOM,然后將組件的內(nèi)容渲染出來;
  • 渲染器在渲染組件時,需要先通過執(zhí)行組件的渲染函數(shù)拿到返回值即組件要渲染的內(nèi)容,可以稱為為subTree,最后再遞歸調(diào)用渲染器將subTree渲染出來即可

組件可以通過函數(shù)JS對象來實現(xiàn)

  • 通過函數(shù)實現(xiàn)時:該函數(shù)返回一個描述DOM節(jié)點的虛擬DOM即可,此時渲染器的Tag屬性值就是該組件函數(shù)了,對應(yīng)渲染器中也需要進行判斷Tag為函數(shù)時進行特殊處理即可(即通過執(zhí)行該函數(shù)拿到對應(yīng)描述普通節(jié)點的虛擬DOM然后執(zhí)行渲染器renderer即可)
  • 通過JS對象實現(xiàn)時:其renderer返回值就是一個描述節(jié)點的虛擬DOM,因此可以直接執(zhí)renderer函數(shù)即可得到虛擬DOM
// MyComponent 是一個對象
const MyComponent = {
  render() {
    return {
      tag: "div",
      props: {
        onClick: () => alert("hello"),
      },
      children: "click me",
    };
  },
};
function mountComponent(vnode, container) {
  // 調(diào)用組件函數(shù),獲取組件要渲染的內(nèi)容(虛擬 DOM)
  const subtree = vnode.tag();
  // 遞歸地調(diào)用 renderer 渲染 subtree
  renderer(subtree, container);
}
// MyComponent 是一個函數(shù)
function renderer(vnode, container) {
  if (typeof vnode.tag === "string") {
    // 說明 vnode 描述的是標(biāo)簽元素
    // mountElement內(nèi)部實現(xiàn)與下文的「實現(xiàn)renderer渲染器邏輯一致」
    mountElement(vnode, container);
  } else if (typeof vnode.tag === "function") {
    // 說明 vnode 描述的是組件
    mountComponent(vnode, container);
  }
}
function mountComponent(vnode, container) {
  // 調(diào)用組件函數(shù),獲取組件要渲染的內(nèi)容(虛擬 DOM)
  const subtree = vnode.tag();
  // 遞歸地調(diào)用 renderer 渲染 subtree
  renderer(subtree, container);
}

render與renderer

  • renderer代表渲染器,其作用是將虛擬DOM渲染為特定平臺上的真實DOM,如在瀏覽器平臺上,渲染器會將虛擬DOM渲染為真實DOM
  • render表示渲染,是執(zhí)行的動作
  • 渲染器不僅用來渲染,還可以用來執(zhí)行其他操作,如激活已有DOM、SSR等;是更寬泛的概念,renderer包含render;
  • 渲染器除了普通的創(chuàng)建節(jié)點功能外,還需要實現(xiàn)精確的定點更新對應(yīng)變化的虛擬DOM到界面上,其內(nèi)部原理簡單,歸根結(jié)底就是通過熟悉的DOM操作API來完成渲染工作

實現(xiàn)renderer渲染器

function renderer(vnode, container) {
  // 使用 vnode.tag 作為標(biāo)簽名稱創(chuàng)建對應(yīng)的 DOM 元素
  const el = document.createElement(vnode.tag);
  // 遍歷 vnode.props,將屬性、事件添加到 DOM 元素
  for (const key in vnode.props) {
    if (/^on/.test(key)) {
      // 如果 key 以 on 開頭,說明它是事件
      el.addEventListener(
        key.substr(2).toLowerCase(), // 事件名稱 onClick ---> click
        vnode.props[key] // 事件處理函數(shù)
      );
    }
  }
  // 處理 children
  if (typeof vnode.children === "string") {
    // 如果 children 是字符串,說明它是元素的文本子節(jié)點
    el.appendChild(document.createTextNode(vnode.children));
  } else if (Array.isArray(vnode.children)) {
    // 遞歸地調(diào)用 renderer 函數(shù)渲染子節(jié)點,使用當(dāng)前元素 el 作為掛載點
    vnode.children.forEach((child) => renderer(child, el));
  }
  // 將元素添加到掛載點下
  container.appendChild(el);
}
  • 創(chuàng)建元素:對應(yīng)虛擬DOM中的Tag屬性
  • 為創(chuàng)建的元素添加屬性和事件:對應(yīng)虛擬DOM中的Props屬性
  • 添加子元素:對應(yīng)虛擬DOM中的children屬性
    • 這里的children可以是數(shù)組或字符串,數(shù)組時需要以剛才新建的DOM節(jié)點為父節(jié)點進行回調(diào)渲染器renderer進行遞歸渲染,當(dāng)是普通字符串時表明子節(jié)點是一個普通文本,直接調(diào)用createTextNode API進行創(chuàng)建后添加到新創(chuàng)建的元素內(nèi)部即可

具體代碼實現(xiàn)邏輯

角色解析

  • 控制著Vue生命周期里試圖的掛載、更新和渲染

具體作用

  • 創(chuàng)建VNode(h函數(shù))
  • 掛載(mount)/渲染(render)/更新(patch)
  • 渲染的核心diff算法

Vue3特殊內(nèi)置組件解析

<template>
   // Portal 把里面的內(nèi)容掛載到 #app
  <Portal target="#app">
    <div class="overlay"></div>
  </Portal>
</template>
  • Fragment
    • 只將該VNode的子節(jié)點渲染到頁面上
    • 相當(dāng)于Vue2中的template標(biāo)簽
  • Portal
    • 允許將其中的內(nèi)容渲染到任何地方

渲染器階段分析

mount掛載階段

mount就是將VNode掛載到真實DOM上

patch階段

patch就是使用新的VNode和舊的VNode進行對比,用最少的資源實現(xiàn)DOM更新,也叫「打補丁」

簡單實現(xiàn)

渲染器接受兩個參數(shù),要被渲染的VNode和掛載點(承載內(nèi)容的container)

function createRenderer() {
  function render(vnode, container) {
    if (vnode) {
      // 存在舊節(jié)點  需要進行patch補丁更新
      patch(container._vnode, vnode, container);
    } else {
      if (container._vnode) {
        // 舊 vnode 存在,且新 vnode 不存在,此時渲染的是上一步中的節(jié)點值,說明是卸載(unmount)操作
        container.innerHTML = "";
      }
    }
    // 把 vnode 存儲到 container._vnode 下,即后續(xù)渲染中的舊 vnode
    container._vnode = vnode;
  }
  return {
    render,
  };
}

編譯器

編譯器在模板編譯時可以識別哪些是靜態(tài)屬性,哪些是動態(tài)屬性,從而在編譯生成代碼時可以將這些信息附加到編譯后代碼中,這樣可以避免渲染器花費力氣去尋找變更點

相關(guān)概念

編譯器和渲染器一樣,不同之處在于編譯器是將模板編譯成渲染函數(shù),而模板就是一個普通的字符串,編譯器會分析該字符串并生成一個功能與之相同的渲染函數(shù);
模板在Vue中體現(xiàn)在.vue文件中的<template>標(biāo)簽的內(nèi)容,本身.vue文件就是一個組件,編譯器會將模板內(nèi)容編譯成渲染函數(shù)并添加到<script>標(biāo)簽的組件對象上;

<template>
  <div @click="login">
    登錄
  </div>
</template>
<script>
  export default {
    data() {
    },
    methods: {
      login: () => { }
    }
  }
</script>
//編譯后
export default {
  data() {},
  methods: {
    login: () => { }
  },
  render() {
    return h('div', { onClick: login }, '登錄')
  }
}

總結(jié)

通過將渲染器和編譯器相配合,從而達到進一步提升性能的目的

  • 虛擬DOM和模板都可以描述UI,虛擬DOM比模板更加靈活,模板比虛擬DOM更加直觀

組件的實現(xiàn)需要依賴于渲染器,模板的編譯需要依賴于編譯器,而且編譯后的代碼是根據(jù)渲染器和虛擬DOM的設(shè)計決定的,因此Vue中各個模塊之間是相互關(guān)聯(lián)、相互制約的;

模板工作原理:無論是模板還是直接手寫渲染函數(shù),對于一個組件來說,其渲染內(nèi)容最終都是通過渲染函數(shù)產(chǎn)生的,然后渲染器再將渲染函數(shù)返回 的虛擬DOM渲染為真實DOM

以上就是Vue3渲染器與編譯器深入淺析的詳細(xì)內(nèi)容,更多關(guān)于Vue3渲染器編譯器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vuex中的四個map方法的使用小結(jié)

    vuex中的四個map方法的使用小結(jié)

    vuex里面有四個map方法,他們分別可以針對不同的元素進行不同的代碼生成,本文就來詳細(xì)的介紹一下vuex中的四個map方法,具有一定的參考價值,感興趣的可以了解一下
    2023-05-05
  • 如何解決Vue3組合式API模式下動態(tài)組件不渲染問題

    如何解決Vue3組合式API模式下動態(tài)組件不渲染問題

    這篇文章主要介紹了如何解決Vue3組合式API模式下動態(tài)組件不渲染問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教<BR>
    2024-03-03
  • Vue?click事件傳遞參數(shù)的示例教程

    Vue?click事件傳遞參數(shù)的示例教程

    這篇文章主要介紹了Vue?click事件傳遞參數(shù)--方法/教程/實例,本文用示例介紹Vue中事件傳參的方法,采用click這個事件進行展示,結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • el-tree設(shè)置選中高亮/焦點高亮、選中節(jié)點加深背景及更改字體顏色等的方法

    el-tree設(shè)置選中高亮/焦點高亮、選中節(jié)點加深背景及更改字體顏色等的方法

    el-tree默認(rèn)有較淺的背景色,這里業(yè)務(wù)需要,選中節(jié)點的字體高亮,更改顏色,下面這篇文章主要給大家介紹了關(guān)于el-tree選中高亮/焦點高亮、選中節(jié)點加深背景及更改字體顏色等的設(shè)置方法,需要的朋友可以參考下
    2022-12-12
  • vue-cli項目使用vue-picture-preview圖片預(yù)覽組件方式

    vue-cli項目使用vue-picture-preview圖片預(yù)覽組件方式

    這篇文章主要介紹了vue-cli項目使用vue-picture-preview圖片預(yù)覽組件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue+elementUI實現(xiàn)動態(tài)面包屑

    vue+elementUI實現(xiàn)動態(tài)面包屑

    這篇文章主要為大家詳細(xì)介紹了vue+elementUI實現(xiàn)動態(tài)面包屑,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • vue+element下日期組件momentjs轉(zhuǎn)換賦值問題解決

    vue+element下日期組件momentjs轉(zhuǎn)換賦值問題解決

    這篇文章主要介紹了vue+element下日期組件momentjs轉(zhuǎn)換賦值問題,記錄下使用momentjs轉(zhuǎn)換日期字符串賦值給element的日期組件報錯問題,需要的朋友可以參考下
    2024-02-02
  • Vue的diff算法原理你真的了解嗎

    Vue的diff算法原理你真的了解嗎

    這篇文章主要為大家詳細(xì)介紹了Vue的diff算法原理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 深入探討Vue計算屬性與監(jiān)聽器的區(qū)別和用途

    深入探討Vue計算屬性與監(jiān)聽器的區(qū)別和用途

    在Vue的開發(fā)中,計算屬性(Computed Properties)和監(jiān)聽器(Watchers)是兩種非常重要的概念,它們都用于響應(yīng)式地處理數(shù)據(jù)變化,本文將帶你深入了解計算屬性和監(jiān)聽器的區(qū)別,以及在何時使用它們,感興趣的朋友可以參考下
    2023-09-09
  • VUE登錄注冊頁面完整代碼(直接復(fù)制)

    VUE登錄注冊頁面完整代碼(直接復(fù)制)

    這篇文章主要給大家介紹了關(guān)于VUE登錄注冊頁面的相關(guān)資料,在Vue中可以使用組件來構(gòu)建登錄注冊頁面,文中通過圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12

最新評論