1

petite-vue源码剖析-优化手段template详解 - ^_^肥仔John

 2 years ago
source link: https://www.cnblogs.com/fsjohnhuang/p/16011271.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

什么是<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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK