Vue:条件渲染 (Conditional Rendering)

1. 核心指令:v-if

作用 :用于条件性地渲染 一块内容。这块内容只会在指令的表达式返回真值 (truthy value) 时才被渲染和保留在 DOM 中

语法

html 复制代码
<h1 v-if="awesome">Vue is awesome!</h1>

工作机制

  • 当 awesome 为真值时,

    元素会被创建并插入到 DOM 中。

  • 当 awesome 变为假值时,Vue 会销毁该元素及其内部的事件监听器和子组件(触发相应的生命周期钩子)。

  • 当 awesome 再次变为真值时,Vue 会重新创建该元素及其内容(再次触发生命周期钩子)。

特点:是"真正"的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件被正确地销毁和重建。

2. 辅助指令:v-else

作用 :为 v-if 添加一个"else 区块"。必须紧跟在 v-if 或 v-else-if 元素后面,否则它将无法被识别。

语法

html 复制代码
<button @click="awesome = !awesome">Toggle</button>

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

注意 :v-else 不需要任何表达式。

3. 辅助指令:v-else-if

作用 :提供相当于 v-if 的"else if 区块"。可以连续多次重复使用,用于实现多个分支的条件判断。

语法

html 复制代码
<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>

注意 :和 v-else 类似,一个使用 v-else-if 的元素必须紧跟 在一个 v-if 或一个 v-else-if 元素后面。

4. 在 <template> 上使用 v-if

问题v-if 必须依附于单个元素。如果想切换多个元素,包裹一个 div 有时会破坏 HTML 结构。

解决方案 :可以在一个 <template> 元素上使用 v-if。<template> 是一个不可见的包装器元素,最终的渲染结果不会包含它

语法

html 复制代码
<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

注意 :v-else 和 v-else-if 同样可以在 <template> 上使用。

5. 替代指令:v-show

作用 :另一个用于按条件显示 一个元素的指令。元素始终会被渲染并保留在 DOM 中 ,v-show 只是简单地切换该元素的 CSS display 属性。

语法

html 复制代码
<h1 v-show="ok">Hello!</h1>

限制

  • 不支持 在 <template> 元素上使用。

  • 不能 和 v-else 搭配使用。

6. v-if vs. v-show 核心对比

特性 v-if v-show
工作机制 条件性地渲染/销毁元素 始终渲染 ,仅切换 CSS display 属性
编译/渲染 惰性的:初始为 false 则不编译 无论条件如何,初始都会编译
DOM 操作 操作 DOM 节点的添加和移除 仅操作 CSS 样式
性能开销 更高的切换开销(尤其是初始为 false 时) 更高的初始渲染开销(无论是否显示都要渲染)
适用场景 运行时条件很少改变 ,或需要避免初始渲染 需要非常频繁切换的场景

选择策略流程图

7. 重要注意事项

v-ifv-for 的优先级

规则 :当 v-if 和 v-for 同时用于同一个元素 时,v-if 会首先被执行

强烈建议不要在同一元素上使用这两个指令。可以通过以下方式解决:

  1. 使用 <template> 包装 :将 v-for 放在 <template> 上,v-if 放在内部元素上。

  2. 使用计算属性 :预先通过计算属性过滤列表,避免同时需要 v-if 和 v-for。

示例 (不推荐)

html 复制代码
<!-- 不推荐的做法 -->
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo.name }}
</li>

示例 (推荐)

html 复制代码
<!-- 推荐做法 1: 使用 <template> -->
<template v-for="todo in todos">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>

<!-- 推荐做法 2: 使用计算属性 -->
<li v-for="todo in incompleteTodos">
  {{ todo.name }}
</li>
// ...
computed: {
  incompleteTodos() {
    return this.todos.filter(todo => !todo.isComplete);
  }
}

8. 总结

  1. v-if、v-else-if、v-else 是一套用于实现条件块渲染/销毁的指令链,它们控制的是元素是否存在於 DOM 中。

  2. v-show 是一个独立的指令,它通过 CSS 控制元素的显示与隐藏,元素始终存在于 DOM 中

  3. 选择 v-if 还是 v-show 取决于你的具体需求:

    • 需要频繁切换 (如 tabs 切换)? -> v-show

    • 条件在运行时很少改变 ,或希望减少初始负载 ? -> v-if

  4. 绝对避免 在同一个元素上同时使用 v-if 和 v-for。如果需要,请使用 <template> 标签或计算属性来拆分逻辑。

  5. 使用 <template> 标签可以对多个元素进行分组条件渲染,而无需引入多余的 DOM 元素。

相关推荐
柯南二号2 小时前
【大前端】前端生成二维码
前端·二维码
程序员码歌2 小时前
明年35岁了,如何破局?说说心里话
android·前端·后端
博客zhu虎康3 小时前
React Hooks 报错?一招解决useState问题
前端·javascript·react.js
灰海3 小时前
vue中通过heatmap.js实现热力图(多个热力点)热区展示(带鼠标移入弹窗)
前端·javascript·vue.js·heatmap·heatmapjs
王源骏4 小时前
LayaAir鼠标(手指)控制相机旋转,限制角度
前端
大虾写代码4 小时前
vue3+TS项目配置Eslint+prettier+husky语法校验
前端·vue·eslint
wordbaby4 小时前
用 useEffectEvent 做精准埋点:React analytics pageview 场景的最佳实践与原理剖析
前端·react.js
上单带刀不带妹5 小时前
在 ES6 中如何提取深度嵌套的对象中的指定属性
前端·ecmascript·es6
excel5 小时前
使用热力贴图和高斯函数生成山峰与等高线的 WebGL Shader 解析
前端