likes
comments
collection
share

条件渲染

作者站长头像
站长
· 阅读数 16

v-if / v-else-if / v-else

v-if 指令用于条件性的渲染一块内容。这块内容只有在指令的表达式返回 true 的时候被渲染。

<template>
  <div>
    <h1 v-if="awesome">Vue is awesome!</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      awesome: true,
    };
  },
};
</script>

也可以使用 v-else 添加一个 else 块。

需要注意点的是,v-else 必须跟在 v-ifv-else-if 的后面,否则它将不被识别。

<template>
  <div>
    <h1 v-if="awesome">Vue is awesome!</h1>
    <h1 v-else>Oh no 😢</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      awesome: false,
    };
  },
};
</script>

v-else-if,是 v-if 的后置判断,可以连续使用。它需要跟在 v-ifv-else-if 的后面。

<template>
  <div>
    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else-if="type === 'C'">C</div>
    <div v-else>Not A/B/C</div>
  </div>
</template>

用 key 管理可复用的元素

v-if 指令控制元素是否渲染,而 Vue 为了尽可能高效的渲染元素,通常会复用已有的元素,而不是从头开始渲染。

<template>
  <div>
    <template v-if="type === 'username'">
      <label>用户名:</label>
      <input placeholder="请输入用户名" />
    </template>
    <template v-else>
      <label>邮箱:</label>
      <input placeholder="请输入邮箱" />
    </template>

    <button
      style="margin-left: 12px"
      @click="type = type === 'username' ? 'email' : 'username'"
    >
      切换
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      type: "username",
    };
  },
};
</script>

在点击 切换 的时候会发现输入框的值并未因为重新渲染而清空。

Vue 在数据更新的时候通过 diff 算法对 新的vnode旧的vnode 进行比对,因为没有设置 key 所以在对比时发现新/旧节点结构没有发生变化,所以并没有创建新的 DOM ,只是针对了内容做了更新。就出现了点击 切换 时数据没有清空的情况。

设置了 key 值后:

<template>
  <div>
    <template v-if="type === 'username'">
      <label>用户名:</label>
      <input placeholder="请输入用户名" key="username"/>
    </template>
    <template v-else>
      <label>邮箱:</label>
      <input placeholder="请输入邮箱" key="email"/>
    </template>

    <button
      style="margin-left: 12px"
      @click="type = type === 'username' ? 'email' : 'username'"
    >
      点击
    </button>
  </div>
</template>

设置了 key 后每次切换都会对 input 元素重新渲染。

v-show

v-show 指令做条件判断的元素,始终会被渲染到页面中。只是通过 display 属性控制显示或隐藏。

<template> 标签不支持 v-show,因为 v-show 始终会被渲染 DOM 结构。而 <template> 标签在渲染时不会产生 DOM 结构。

v-if 和 v-show 的使用场景和区别

  • 区别:
    • v-if 控制元素的销毁创建
    • v-show 则只是通过 display 控制显示隐藏
    • v-if惰性 的,如果初始渲染时条件是 false ,则不会渲染内容,只有为 true,才渲染。
    • v-show 无论初始时条件时 true 或是 false 都会渲染内容。
  • 使用场景:
    • 切换的非常频繁建议使用 v-showv-if 有更高的切换开销。

v-if 和 v-for 一起使用

v-ifv-for 一起使用时,v-for 具有比 v-if 更高的优先级。

两者在一起使用:

<template>
  <div>
    <ul>
      <li v-for="(item, index) in ['1', '2', '3']" :key="index" v-if="true">
        {{ item }}
      </li>
    </ul>
  </div>
</template>

因为 v-for 优先级比 v-if 高,所以会渲染成:

<li v-if="true">1</li>
<li v-if="true">2</li>
<li v-if="true">3</li>

如果你想控制是否渲染该列表可以将 v-if 设置在外层,而不是和 v-for 一起使用。