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

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

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

渲染器

相關(guān)概念

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

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

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

  • 通過函數(shù)實(shí)現(xiàn)時(shí):該函數(shù)返回一個(gè)描述DOM節(jié)點(diǎn)的虛擬DOM即可,此時(shí)渲染器的Tag屬性值就是該組件函數(shù)了,對(duì)應(yīng)渲染器中也需要進(jìn)行判斷Tag為函數(shù)時(shí)進(jìn)行特殊處理即可(即通過執(zhí)行該函數(shù)拿到對(duì)應(yīng)描述普通節(jié)點(diǎn)的虛擬DOM然后執(zhí)行渲染器renderer即可)
  • 通過JS對(duì)象實(shí)現(xiàn)時(shí):其renderer返回值就是一個(gè)描述節(jié)點(diǎn)的虛擬DOM,因此可以直接執(zhí)renderer函數(shù)即可得到虛擬DOM
// MyComponent 是一個(gè)對(duì)象
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 是一個(gè)函數(shù)
function renderer(vnode, container) {
  if (typeof vnode.tag === "string") {
    // 說明 vnode 描述的是標(biāo)簽元素
    // mountElement內(nèi)部實(shí)現(xiàn)與下文的「實(shí)現(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渲染為特定平臺(tái)上的真實(shí)DOM,如在瀏覽器平臺(tái)上,渲染器會(huì)將虛擬DOM渲染為真實(shí)DOM
  • render表示渲染,是執(zhí)行的動(dòng)作
  • 渲染器不僅用來渲染,還可以用來執(zhí)行其他操作,如激活已有DOM、SSR等;是更寬泛的概念,renderer包含render;
  • 渲染器除了普通的創(chuàng)建節(jié)點(diǎn)功能外,還需要實(shí)現(xiàn)精確的定點(diǎn)更新對(duì)應(yīng)變化的虛擬DOM到界面上,其內(nèi)部原理簡(jiǎn)單,歸根結(jié)底就是通過熟悉的DOM操作API來完成渲染工作

實(shí)現(xiàn)renderer渲染器

function renderer(vnode, container) {
  // 使用 vnode.tag 作為標(biāo)簽名稱創(chuàng)建對(duì)應(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é)點(diǎn)
    el.appendChild(document.createTextNode(vnode.children));
  } else if (Array.isArray(vnode.children)) {
    // 遞歸地調(diào)用 renderer 函數(shù)渲染子節(jié)點(diǎn),使用當(dāng)前元素 el 作為掛載點(diǎn)
    vnode.children.forEach((child) => renderer(child, el));
  }
  // 將元素添加到掛載點(diǎn)下
  container.appendChild(el);
}
  • 創(chuàng)建元素:對(duì)應(yīng)虛擬DOM中的Tag屬性
  • 為創(chuàng)建的元素添加屬性和事件:對(duì)應(yīng)虛擬DOM中的Props屬性
  • 添加子元素:對(duì)應(yīng)虛擬DOM中的children屬性
    • 這里的children可以是數(shù)組或字符串,數(shù)組時(shí)需要以剛才新建的DOM節(jié)點(diǎn)為父節(jié)點(diǎn)進(jìn)行回調(diào)渲染器renderer進(jìn)行遞歸渲染,當(dāng)是普通字符串時(shí)表明子節(jié)點(diǎn)是一個(gè)普通文本,直接調(diào)用createTextNode API進(jìn)行創(chuàng)建后添加到新創(chuàng)建的元素內(nèi)部即可

具體代碼實(shí)現(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é)點(diǎn)渲染到頁面上
    • 相當(dāng)于Vue2中的template標(biāo)簽
  • Portal
    • 允許將其中的內(nèi)容渲染到任何地方

渲染器階段分析

mount掛載階段

mount就是將VNode掛載到真實(shí)DOM上

patch階段

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

簡(jiǎn)單實(shí)現(xiàn)

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

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

編譯器

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

相關(guān)概念

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

<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é)

通過將渲染器和編譯器相配合,從而達(dá)到進(jìn)一步提升性能的目的

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

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

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

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

相關(guān)文章

  • 從0到1構(gòu)建vueSSR項(xiàng)目之路由的構(gòu)建

    從0到1構(gòu)建vueSSR項(xiàng)目之路由的構(gòu)建

    這篇文章主要介紹了從0到1構(gòu)建vueSSR項(xiàng)目之路由的構(gòu)建,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • vue中mock數(shù)據(jù),模擬后臺(tái)接口實(shí)例

    vue中mock數(shù)據(jù),模擬后臺(tái)接口實(shí)例

    這篇文章主要介紹了vue中mock數(shù)據(jù),模擬后臺(tái)接口實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue中的情侶屬性$dispatch和$broadcast詳解

    Vue中的情侶屬性$dispatch和$broadcast詳解

    這篇文章主要給大家介紹了關(guān)于Vue中情侶屬性$dispatch和$broadcast的相關(guān)資料,文中通過示例代碼以及圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • TinyMCE富文本編輯器在Vue中的使用方式

    TinyMCE富文本編輯器在Vue中的使用方式

    這篇文章主要介紹了TinyMCE富文本編輯器在Vue中的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 淺談Ant Design Pro 菜單自定義 icon

    淺談Ant Design Pro 菜單自定義 icon

    這篇文章主要介紹了Ant Design Pro 菜單自定義 icon,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 探秘Vue異步更新機(jī)制中nextTick的原理與實(shí)現(xiàn)

    探秘Vue異步更新機(jī)制中nextTick的原理與實(shí)現(xiàn)

    nextTick?是?Vue?提供的一個(gè)重要工具,它的作用主要體現(xiàn)在幫助我們更好地處理異步操作,下面就跟隨小編一起來探索一下nextTick的原理與實(shí)現(xiàn)吧
    2024-02-02
  • vue中this.$confirm的使用及說明

    vue中this.$confirm的使用及說明

    這篇文章主要介紹了vue中this.$confirm的使用及說明方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 使用Vant如何完成各種Toast提示框

    使用Vant如何完成各種Toast提示框

    這篇文章主要介紹了使用Vant如何完成各種Toast提示框,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • vue組件開發(fā)之slider組件使用詳解

    vue組件開發(fā)之slider組件使用詳解

    這篇文章主要為大家詳細(xì)介紹了vue組件開發(fā)之slider組件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • Vue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例

    Vue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例

    下面小編就為大家?guī)硪黄猇ue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10

最新評(píng)論

丹阳市| 庄浪县| 吕梁市| 安仁县| 宁陕县| 秦皇岛市| 宁乡县| 永顺县| 通山县| 金华市| 嘉荫县| 佛学| 天祝| 若尔盖县| 津南区| 石河子市| 康定县| 东乡县| 崇文区| 千阳县| 井冈山市| 柳河县| 安多县| 黄山市| 富蕴县| 林州市| 景宁| 信宜市| 嘉定区| 酒泉市| 沁阳市| 巴林右旗| 谷城县| 竹北市| 监利县| 青海省| 万载县| 高雄县| 哈尔滨市| 冕宁县| 时尚|