Vue 模板语法——文本插值和常用指令(2)

205 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1. v-once 指令

v-once 用于指定元素或组件只渲染一次。

  • 当数据发生变化时,元素或组件1及其所有的子节点都将被视为静态内容并跳过;
  • 这可以用于(更新)性能优化。
<template id="my-app">
  <h2>{{ counter }}</h2>
  <!-- 单个元素 -->
  <h2 v-once>{{ counter }}</h2>
  <!-- 有子元素 -->
  <!-- 使用了 v-once 指定后,无论是 counter 还是 message 发生改变,此 div 元素
    及其所有子元素都不会再被重新渲染(对应的显示内容不会再更新)。不会被重新渲染就意味着
    之后在进行 patch 也就是更新时,对应的内容就不需要更新,所以更新性能就会提高一点 -->
  <div v-once>
    <h2>{{ counter }}</h2>
    <h2>{{ message }}</h2>
  </div>
  <button @click="increment">+1</button>
</template>

完整代码如下:

<div id="app"></div>

<template id="my-app">
  <h2>{{ counter }}</h2>
  <!-- 单个元素 -->
  <h2 v-once>{{ counter }}</h2>
  <!-- 有子元素 -->
  <!-- 使用了 v-once 指定后,无论是 counter 还是 message 发生改变,此 div 元素
    及其所有子元素都不会再被重新渲染(对应的显示内容不会再更新)。不会被重新渲染就意味着
    之后在进行 patch 也就是更新时,对应的内容就不需要更新,所以更新性能就会提高一点 -->
  <div v-once>
    <h2>{{ counter }}</h2>
    <h2>{{ message }}</h2>
  </div>
  <button @click="increment">+1</button>
</template>

<script src="./js/vue.js"></script>
<script>
  const App = {
    data() {
      return {
        counter: 100,
        message: '你好'
      }
    },
    methods: {
      increment() {
        this.counter++;
      }
    },
    template: '#my-app'
  };

  Vue.createApp(App).mount('#app');
</script>

2. v-text 指令

用于更新元素的 textContent

  • 示例:

    <h2 v-text="message"></h2>
    

    等价于:

    <h2>{{ message }}</h2>
    

但如果要更新 textContent 中的部分内容,需要使用 Mustache 插值:

  • 示例:

    <h2>消息内容:{{ message }},我还能拼接别的内容</h2>
    

可见,Mustache 语法相对来说更加灵活,它还能拼接一些其它内容。所以我们一般用的 Mustache 语法,v-text 指令用得较少。

3. v-html 指令

用于更新元素的 innerHTML

  • 默认情况下,如果我们展示的内容中存在普通 HTML 代码,那么 Vue 不会对其进行特殊处理(不会将其作为 Vue 模板进行编译);

  • 如果希望内容中的 HTML 可以被 Vue 解析出来,则可以使用 v-html

    • 示例:

      <h2 v-html="message"></h2>
      

      完整代码如下:

      <div id="app"></div>
      
      <template id="my-app">
        <!-- 默认展示 -->
        <p>{{ message }}</p>
        <!-- 使用 v-html 展示 -->
        <p v-html="message"></p>
      </template>
      
      <script src="./js/vue.js"></script>
      <script>
        const App = {
          data() {
            return {
              message: '内容中存在 HTML:<span style="color: orangered; background-color: #c7decc;">从天宫看太空</span>'
            }
          },
          template: '#my-app'
        };
      
        Vue.createApp(App).mount('#app');
      </script>
      

4. v-pre 指令

v-pre 用于跳过这个元素及其子元素的编译过程。可以用来显示原始 Mustache 标签:

  • 示例:

    <!-- 页面对应的显示内容:{{ message }} -->
    <div v-pre>{{ message }}</div>
    

跳过(大量)没有指令的节点,或者说跳过不需要编译的节点,可以加快编译速度。

5. v-cloak 指令

这个指令保持在元素上直到关联组件实例结束编译(编译结束后 Vue 会将其删除)。

  • CSS 规则如 [v-cloak] { display: none; } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到组件实例准备完毕。

    • 示例:

    image-20210717145414884.png

    核心代码如下:

    [v-cloak] {
      display: none;
    }
    
    <div v-cloak>{{ message }}</div>
    

    这样一来,<div> 就不会显示,直到编译结束(这时 Vue 会删除元素上的 v-cloak 属性)。如果不这么做,我们这里就可能出现这样一种情况:在 Vue 还没来得及解析 {{ message }} 时,页面呈现的还是 {{ message }},等到解析完了,才会用 message 对应的内容替换掉 {{ message }} 进行呈现。这个过程可能会一闪而过,但却有可能出现(实践中发现在使用 CDN 方式引入 Vue 时有可能出现:

    使用 CDN 引入 Vue 时不使用 v-cloak 时可能出现的情况.gif

    但现在 Vue3 一般不会出现这种过程,这跟它的编译原理有关)。所以,为了防止这种情况的出现,就有了 v-cloak 指令。

  • 但是,在真实开发中,我们现在一般用不上这个指令,因为我们一般会使用 WebpackDevServer,它会自动对模板进行编译(编译成渲染函数了)打包,所以之后不会有未编译的 Mustache 标签这种情况出现。

Footnotes

  1. 组件的概念后面会讲到