petite-vue源碼剖析-優化手段template詳解

什麼是<template>元素?

<template>是2013年定稿用於提供一種更統一、功能更強大的模板本存放方式。具體表現爲

  1. 通過<template>元素屬性content獲取已實例化的HTML元素(不是字符串而已)

    <template id="tpl">
      <div>a</div>
      <div>b</div>
    </template>
    <script>
      const tpl = document.getElementById('tpl')
      tpl.content // document-fragment
      tpl.content.children[0].outerHTML // <div>a</div>
    </script>
    
  2. <template>以及其子節點均不可視

  3. <template>下的img元素的src屬性即使有值也不會發出資源請求

  4. <template>下的script和css規則均不會解析和執行

更多信息請查看:《HTML語義化:HTML5新標籤——template》

v-if搭配<template>

<div v-scope="App"></div>

<script type="module">
  import { createApp } from 'https://unpkg.com/petite-vue?module'

  createApp({
    App: {
      $template: `
      <template v-if="status === 'offline'">
        <span> OFFLINE </span>
      </template>
      <template v-else>
        <span> ONLINE </span>
      </template>
      `,
    }
    status: 'online'
  }).mount('[v-scope]')
</script>

首次渲染過程如下:

  1. 將通過walk.ts中的resolveTemplate方法將App.$template渲染到DOM樹上

    <div v-scope="App">
       <template v-if="status === 'offline'">
         <span> OFFLINE </span>
       </template>
       <template v-else>
         <span> ONLINE </span>
       </template>
    </div>
    
  2. 解析子節點<template v-if="status === 'offline'"></template>

    1. 進入directives/if.ts識別附着v-ifv-else的元素,並將它們從DOM樹中移除
    2. 根據條件表達式status === 'offline'對以離線節點(Dettached Node)<template v-else></template>爲基礎創建塊對象(Block)
    <div v-scope="App">
    </div>
    
  3. 在塊對象的構造函數中會識別<template>元素,並通過content.cloneNode方法複製<template>的子節點作爲模板,進行後續解析處理

    <div v-scope="App">
    </div>
    
  4. 最後directives/if.ts裏會將塊對象插入父節點中且位於錨點元素前面

    <div v-scope="App">
       <span> ONLINE </span>
    </div>
    

小結

  1. 這裏利用的是<template>元素本身的特性實現在線解析用戶不可見(你看不到我,你看不到我:D),和避免如<img src="logo.png">發送無效請求的問題;
  2. 由於<template>是在block.ts中處理獲取模板,因此v-for搭配<template>的原理和v-if是一致的。

錯誤使用

雖然<template>能幫助我們優化用戶體驗和性能,但有些時候也會讓我們掉到坑裏面,下面一起繞過這些坑吧!

<div v-scope="App"></div>

<script type="module">
  import { createApp } from 'https://unpkg.com/petite-vue?module'

  createApp({
    App: {
      $template: `
      <template>
        <div>Hello</div>
      </template>
      `,
    }
    status: 'online'
  }).mount('[v-scope]')
</script>

根塊對象對應的是<div v-scope="App"></div>,而<template>由於沒有附加v-ifv-for,因此不會爲其創建新的塊對象進行處理,最後得到的UI就是這樣的:

<div v-scope="App">
  <template>
    <div>Hello</div>
  </template>
</div>

用於無法看到文字Hello。

總結

通過本篇內容的介紹,我們記得<template>必須搭配v-ifv-for使用哦!
後面我們將探索@vue/reactivity在petite-vue的使用,敬請期待。
尊重原創,轉載請註明來自:https://www.cnblogs.com/fsjohnhuang/p/16011271.html 肥仔John

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章