vue - 内置指令


Vue3 提供了一系列内置指令,用于简化 DOM 操作和实现常见功能。这些指令以 v- 前缀开头,通常用于模板中,以下是详细分类及解析:

一、核心渲染指令

用于控制元素的渲染逻辑和数据绑定。

v-text

  • 功能:更新元素的文本内容(相当于 textContent)。

  • 示例:

    <span v-text="message"></span>
    <!-- 等价于 -->
    <span>{{ message }}</span>
    
  • 特点:会覆盖元素原有的文本,而插值表达式 {{}} 只会替换占位符。

v-html

  • 功能:将数据以 HTML 格式插入元素(相当于 innerHTML)。

  • 示例:

    <div v-html="rawHtml"></div>
    
  • 注意:动态渲染 HTML 存在 XSS 风险,仅用于可信内容,禁止用于用户输入。

v-show

  • 功能:根据表达式的真假值,通过 CSS display 属性控制元素显示/隐藏。

  • 示例:

    <p v-show="isVisible">条件显示</p>
    
  • 特点:元素始终存在于 DOM 中,只是切换显示状态,适合频繁切换的场景。

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

  • 功能:根据表达式的真假值,动态创建/销毁元素(条件渲染)。

  • 示例:

    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else>Other</div>
    
  • 特点:会真实改变 DOM 结构,适合条件较少切换的场景;可与 <template> 配合实现多元素条件渲染。

v-for

  • 功能:基于可迭代数据(数组、对象、字符串等)循环渲染元素。

  • 示例:

    <!-- 遍历数组 -->
    <li v-for="(item, index) in items" :key="index">
      {{ index }}: {{ item.name }}
    </li>
    
    <!-- 遍历对象 -->
    <div v-for="(value, key) in user" :key="key">
      {{ key }}: {{ value }}
    </div>
    
    <!-- 遍历字符串(按字符循环) -->
    <span v-for="char in 'abc'" :key="char">{{ char }}</span>
    
    <!-- 遍历数字(按次数循环,从1开始) -->
    <div v-for="num in 3" :key="num">{{ num }}</div>
    
  • 注意:必须使用 :key 绑定唯一标识,优化渲染性能并避免状态混乱。

二、事件处理指令

用于绑定 DOM 事件。

v-on

  • 功能:绑定事件监听器,缩写为 @

  • 示例:

    <button v-on:click="handleClick">点击</button>
    <button @click="handleClick">点击(缩写)</button>
    
  • 扩展:

    • 支持事件修饰符:@click.stop(阻止冒泡)、@click.prevent(阻止默认行为)等。
    • 支持按键修饰符:@keyup.enter(回车键触发)。
    • 支持自定义事件:@custom-event="handleEvent"
  • <!-- DOM事件绑定 -->
    <button v-on:click="handleClick">点击</button>
    <button @click="handleClick">点击(缩写)</button>
    <form @submit.prevent="handleSubmit">提交</form>
    
    <!-- 自定义事件绑定(组件间通信) -->
    <!-- 父组件 -->
    <ChildComponent @custom-event="handleCustomEvent" />
    
    <!-- 子组件(Vue3 script setup) -->
    <script setup>
    import { emit } from 'vue';
    const emit = defineEmits(['custom-event']);
    // 触发自定义事件并传参
    const triggerEvent = () => emit('custom-event', { id: 1 });
    </script>
    
    <!-- 子组件(Vue2) -->
    <script>
    export default {
      methods: {
        triggerEvent() {
          this.$emit('custom-event', { id: 1 });
        }
      }
    };
    </script>
    

三、属性绑定指令

用于绑定 HTML 属性或组件 props。

v-bind

  • 功能:动态绑定一个或多个属性,缩写为 :

  • 示例:

    <!-- 绑定 HTML 属性 -->
    <img v-bind:src="imageUrl" :alt="imageAlt">
    
    <!-- 绑定 class -->
    <div :class="{ active: isActive, 'text-danger': hasError }"></div>
    
    <!-- 绑定 style -->
    <div :style="{ color: textColor, fontSize: '16px' }"></div>
    
    <!-- 绑定组件 props -->
    <ChildComponent :user="currentUser"></ChildComponent>
    
  • 特点:可绑定任意属性,表达式结果会被解析为属性值。

四、表单输入绑定指令

用于在表单元素和数据之间创建双向绑定。

v-model

  • 功能:简化表单控件的双向数据绑定(本质是 v-bind + v-on 的语法糖)。

  • 支持元素:inputtextareaselect 等。

  • 示例:

    <input v-model="username" type="text">
    <textarea v-model="content"></textarea>
    <select v-model="selectedValue">
      <option value="1">选项1</option>
    </select>
    
  • 修饰符:

    • .trim:自动去除输入首尾空格。
    • .number:将输入转为数字类型。
    • .lazy:在 change 事件而非 input 事件触发时更新数据。

Vue3 中的 v-model 是表单输入绑定的核心指令,它实现了表单控件与组件数据之间的双向绑定。其本质是语法糖,会根据不同的表单元素自动展开为 v-bind(绑定值)和 v-on(监听输入事件)。

下面详细解析 v-model 在各种表单控件中的使用方法:

一、文本输入框(text /textarea)

适用于单行文本、多行文本输入。

  1. 单行文本(input [type="text"])
<template>
  <div>
    <label>用户名:</label>
    <input type="text" v-model="username">
    <p>你输入的是:{{ username }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const username = ref('') // 初始值为空
</script>
  1. 多行文本(textarea)
<template>
  <div>
    <label>个人简介:</label>
    <textarea v-model="intro" rows="3"></textarea>
    <p>简介内容:{{ intro }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const intro = ref('请输入个人简介') // 初始值
</script>
  • 注意:<textarea> 不需要使用 {{}} 插值,v-model 直接绑定即可。

二、复选框(checkbox)

复选框分为单个复选框(布尔值)和多个复选框(数组)两种场景。

  1. 单个复选框(布尔值绑定)
<template>
  <div>
    <label>
      <input type="checkbox" v-model="agree"> 我同意协议
    </label>
    <p>是否同意:{{ agree ? '是' : '否' }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const agree = ref(false) // 初始未勾选
</script>
  1. 多个复选框(数组绑定)
<template>
  <div>
    <label>爱好:</label>
    <div>
      <label>
        <input type="checkbox" v-model="hobbies" value="reading"> 阅读
      </label>
      <label>
        <input type="checkbox" v-model="hobbies" value="sports"> 运动
      </label>
      <label>
        <input type="checkbox" v-model="hobbies" value="coding"> 编程
      </label>
    </div>
    <p>选中的爱好:{{ hobbies }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const hobbies = ref([]) // 初始为空数组
</script>
  • 多个复选框的 v-model 绑定到同一个数组,选中的值会自动添加到数组中。

三、单选按钮(radio)

多个单选按钮组成一组,通过 name 属性关联,v-model 绑定选中的值。

<template>
  <div>
    <label>性别:</label>
    <div>
      <label>
        <input type="radio" v-model="gender" value="male" name="gender"> 男
      </label>
      <label>
        <input type="radio" v-model="gender" value="female" name="gender"> 女
      </label>
    </div>
    <p>选中的性别:{{ gender }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const gender = ref('male') // 初始选中"男"
</script>

四、下拉选择框(select)

下拉选择框分为单选多选两种模式。

  1. 单选下拉框
<template>
  <div>
    <label>城市:</label>
    <select v-model="city">
      <option value="">请选择</option>
      <option value="beijing">北京</option>
      <option value="shanghai">上海</option>
      <option value="guangzhou">广州</option>
    </select>
    <p>选中的城市:{{ city }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const city = ref('') // 初始未选择
</script>
  1. 多选下拉框(添加 multiple 属性)
<template>
  <div>
    <label>喜欢的水果(按住Ctrl可多选):</label>
    <select v-model="fruits" multiple size="3">
      <option value="apple">苹果</option>
      <option value="banana">香蕉</option>
      <option value="orange">橙子</option>
      <option value="grape">葡萄</option>
    </select>
    <p>选中的水果:{{ fruits }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const fruits = ref([]) // 初始为空数组
</script>
  • 多选模式下,v-model 绑定到数组,选中的选项值会添加到数组中。
  • size 属性控制下拉框可见选项数量。

五、其他表单控件

  1. 数字输入框(input [type="number"])
<template>
  <div>
    <label>年龄:</label>
    <input type="number" v-model="age" min="0" max="120">
    <p>年龄值:{{ age }}(类型:{{ typeof age }})</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const age = ref(18) // 初始值为数字类型
</script>
  1. 日期选择器(input [type="date"])
<template>
  <div>
    <label>出生日期:</label>
    <input type="date" v-model="birthday">
    <p>出生日期:{{ birthday }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const birthday = ref('2000-01-01') // 初始值为日期字符串(YYYY-MM-DD)
</script>

六、v-model 修饰符

Vue3 提供了三个常用修饰符,用于处理表单输入:

.trim:自动去除输入内容的首尾空格

<input type="text" v-model.trim="username">

.number:将输入值转为数字类型(若无法转换则保留字符串)

<input type="text" v-model.number="age">
<!-- 输入"18"会转为数字18,输入"abc"仍为字符串"abc" -->

.lazy:在 change 事件触发时更新数据(默认是 input 事件)

<input type="text" v-model.lazy="search">
<!-- 输入时不实时更新,失去焦点或按回车后才更新 -->

总结

v-model 是 Vue 表单处理的核心,通过自动适配不同表单控件,实现了简洁的双向绑定:

  • 文本类(text/textarea):绑定字符串
  • 单个复选框:绑定布尔值
  • 多个复选框:绑定数组(收集选中值)
  • 单选按钮 / 单选下拉框:绑定选中的值
  • 多选下拉框:绑定数组(收集选中值)

配合修饰符 .trim.number.lazy 可以更灵活地处理表单输入,大幅简化了传统 DOM 操作的繁琐流程。

五、其他实用指令

v-pre

  • 功能:跳过元素及其子元素的编译过程,直接渲染原始内容。

  • 示例:

    <div v-pre>{{ 这里的表达式不会被编译 }}</div>
    
  • 适用场景:展示包含 {{ }} 的原始文本,提升编译性能。

v-cloak

  • 功能:在 Vue 实例编译完成前隐藏元素,避免未编译的模板闪烁。

  • 用法:

    [v-cloak] { display: none; }
    
    <div v-cloak>{{ message }}</div>
    
  • 原理:编译完成后,Vue 会自动移除 v-cloak 属性。

v-once

  • 功能:元素或组件只渲染一次,后续数据变化不会重新渲染。

  • 示例:

    <div v-once>{{ message }}</div>
    
  • 适用场景:优化静态内容的渲染性能。

六、特殊元素

在 Vue 3 中,<component><slot><template> 都是特殊的内置元素,各自承担着独特的功能,是 Vue 组件系统的核心组成部分。

1. component:动态组件渲染

  • 作用:用于动态渲染不同的组件,根据 is 属性的值决定渲染哪个组件。
  • 特点:Vue 原生内置,支持动态切换组件,常用于 tabs、条件渲染等场景。

示例

<template>
  <!-- 根据 currentComponent 的值动态渲染组件 -->
  <component :is="currentComponent" />

  <button @click="currentComponent = 'ComponentA'">显示A</button>
  <button @click="currentComponent = 'ComponentB'">显示B</button>
</template>

<script setup>
import { ref } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

const currentComponent = ref('ComponentA') // 初始渲染 ComponentA
</script>
  • is

    属性的值可以是:

    • 组件的选项对象(如导入的组件)
    • 组件的注册名称(字符串)
    • HTML 标签名(如 'div',用于渲染原生元素)

2. slot:组件内容分发

  • 作用:用于定义组件的 “插槽”,允许父组件向子组件内部插入内容,实现组件的复用和定制化。
  • 特点:Vue 原生的内容分发机制,支持默认插槽、具名插槽和作用域插槽。

示例

<!-- 子组件 Child.vue -->
<template>
  <div class="child">
    <!-- 默认插槽:接收父组件传入的默认内容 -->
    <slot>默认内容(父组件没传内容时显示)</slot>

    <!-- 具名插槽:接收父组件指定名称的内容 -->
    <slot name="header"></slot>
  </div>
</template>

<!-- 父组件 Parent.vue -->
<template>
  <Child>
    <!-- 默认插槽内容 -->
    <p>这是默认插槽的内容</p>

    <!-- 具名插槽内容(v-slot 可简写为 #) -->
    <template #header>
      <h2>这是头部插槽的内容</h2>
    </template>
  </Child>
</template>
  • 作用域插槽

    :子组件可以向插槽传递数据,父组件使用

    v-slot:name="scope"
    

接收:

<!-- 子组件 -->
<slot name="item" :data="user"></slot>

<!-- 父组件 -->
<template #item="scope">
  <p>{{ scope.data.name }}</p> <!-- 使用子组件传递的数据 -->
</template>

3. template:模板片段容器

  • 作用:作为一个不可见的容器,用于包裹多个元素或组件,本身不会被渲染到 DOM 中。
  • 特点:
    • 不产生实际 DOM 节点,仅用于逻辑分组。
  • 常与 v-ifv-forv-slot 等指令配合使用。

常见用法

  1. 配合 v-if/v-else 分组元素

    <template v-if="isShow">
     <p>段落1</p>
     <p>段落2</p>
    </template>
    
  2. 配合 v-for 循环多个元素

    <template v-for="(item, index) in list" :key="index">
     <p>{{ item.name }}</p>
     <div>{{ item.desc }}</div>
    </template>
    
  3. 定义具名插槽

    <template #footer>
     <button>底部按钮</button>
    </template>
    

总结

  • <component>:动态渲染组件,核心是 :is 属性。
  • <slot>:实现组件内容分发,支持灵活定制子组件内容。
  • <template>:作为模板片段容器,用于逻辑分组,不渲染实际 DOM。

七、组件

1. Transition — 单元素 / 组件的过渡动画

https://cn.vuejs.org/guide/built-ins/transition

单个元素 / 组件插入、删除、显示隐藏v-if/v-show、组件切换)添加进入 / 离开过渡动画。

它不会渲染额外的 DOM 元素,也不会影响组件的布局。

核心原理

Vue 会在元素进入 / 离开的过程中,自动添加 / 移除 6 个过渡类名(以 v- 为前缀,可通过 name 属性自定义):

  1. 进入阶段v-enter-from(初始状态)→ v-enter-active(动画过程)→ v-enter-to(结束状态)
  2. 离开阶段v-leave-from(初始状态)→ v-leave-active(动画过程)→ v-leave-to(结束状态)

基础使用(CSS 过渡)

<template>
  <button @click="show = !show">切换显示</button>
  <!-- Transition 包裹需要动画的元素 -->
  <Transition name="fade">
    <div v-if="show" class="box">过渡动画演示</div>
  </Transition>
</template>

<script setup>
import { ref } from 'vue'
const show = ref(false)
</script>

<style scoped>
/* 进入/离开的动画过程 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s ease;
}

/* 进入初始状态 & 离开结束状态 */
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

关键属性

属性 作用 示例
name 自定义过渡类名前缀(避免多个 Transition 样式冲突) <Transition name="slide"> → 类名前缀为 slide-
appear 初始渲染时是否执行过渡动画 <Transition appear>
mode 控制进入 / 离开的时序(解决元素切换时的重叠问题) mode="out-in"(先出后入)/ mode="in-out"(先入后出)
duration 手动设置过渡时长(ms) :duration="500":duration="{ enter: 300, leave: 600 }"

适用场景

  • 单个元素的显隐切换(v-if/v-show
  • 单个组件的切换(component :is="xxx"
  • 路由切换的过渡(需配合 Vue Router,包裹 <RouterView>

实战:路由过渡动画

<template>
  <RouterView v-slot="{ Component }">
    <Transition name="route-fade" mode="out-in">
      <component :is="Component" />
    </Transition>
  </RouterView>
</template>

<style>
.route-fade-enter-active, .route-fade-leave-active {
  transition: all 0.4s ease;
}
.route-fade-enter-from {
  opacity: 0;
  transform: translateX(30px);
}
.route-fade-leave-to {
  opacity: 0;
  transform: translateX(-30px);
}
</style>

Transition + animate.css

自定义过渡 class

你也可以向 <Transition> 传递以下的 props 来指定自定义的过渡 class:

  • enter-from-class
  • enter-active-class
  • enter-to-class
  • leave-from-class
  • leave-active-class
  • leave-to-class

你传入的这些 class 会覆盖相应阶段的默认 class 名。这个功能在你想要在 Vue 的动画机制下集成其他的第三方 CSS 动画库时非常有用,比如 Animate.css

https://animate.style/

<!-- TransitionAnimate.vue -->
<template>
  <div class="demo-container">
    <!-- 触发按钮 -->
    <button @click="show = !show" class="toggle-btn">
      {{ show ? '隐藏元素' : '显示元素' }}
    </button>

    <!-- Transition 结合 animate.css -->
    <Transition
      enter-active-class="animate__animated animate__fadeInDown"
      leave-active-class="animate__animated animate__fadeOutDown"
      :duration="{ enter: 500, leave: 300 }"
    >
      <div v-if="show" class="animated-box" v-show="show">
        我是带 animate.css 动画的元素 🎉
      </div>
    </Transition>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import 'animate.css'

// 控制元素显示/隐藏
const show = ref(false)
</script>

<style scoped>
.demo-container {
  padding: 20px;
}

.toggle-btn {
  padding: 8px 16px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  margin-bottom: 20px;
}

.animated-box {
  width: 300px;
  height: 150px;
  line-height: 150px;
  text-align: center;
  background: #f0f7ff;
  border: 1px solid #42b983;
  border-radius: 8px;
}
</style>

2. TransitionGroup — 列表的过渡动画

https://cn.vuejs.org/guide/built-ins/transition-group

列表元素插入、删除、排序添加过渡动画,是 <Transition> 的列表专用版本。

核心特性

  1. 默认会渲染一个 <span> 标签,可通过 tag 属性自定义(如 tag="ul")。
  2. 列表元素必须添加唯一 key,否则动画会失效。
  3. 支持移动动画(通过 v-move 类名实现,基于 FLIP 算法)。

基础使用(列表增删动画)

<template>
  <button @click="addItem">添加元素</button>
  <button @click="removeItem">删除最后一个</button>

  <TransitionGroup name="list" tag="ul">
    <li v-for="item in list" :key="item.id" class="list-item">
      {{ item.text }}
    </li>
  </TransitionGroup>
</template>

<script setup>
import { ref } from 'vue'
const list = ref([
  { id: 1, text: '列表项 1' },
  { id: 2, text: '列表项 2' }
])
let nextId = 3

const addItem = () => {
  list.value.push({ id: nextId++, text: `列表项 ${nextId-1}` })
}
const removeItem = () => {
  list.value.pop()
}
</script>

<style scoped>
.list-item {
  padding: 8px;
  margin: 4px 0;
  background: #f0f0f0;
  border-radius: 4px;
}
/* 进入/离开动画 */
.list-enter-active, .list-leave-active {
  transition: all 0.3s ease;
}
.list-enter-from, .list-leave-to {
  opacity: 0;
  transform: translateY(10px);
}
/* 解决删除时元素塌陷的问题 */
.list-leave-active {
  position: absolute;
}
</style>

移动动画(列表排序)

添加 v-move 类名,实现列表排序时的平滑移动效果:

/* 列表元素移动时的动画 */
.list-move {
  transition: transform 0.3s ease;
}

关键属性

继承 <Transition> 的所有属性,额外新增:

属性 作用 示例
tag 自定义渲染的容器标签 <TransitionGroup tag="ol">
move-class 自定义移动动画的类名(替代默认的 v-move move-class="list-move"

适用场景

  • 动态列表的增删(如待办清单、搜索结果列表)
  • 可排序列表(如拖拽排序、筛选排序后的动画)

3. KeepAlive — 组件状态缓存

https://cn.vuejs.org/guide/built-ins/keep-alive.html

缓存不活动的组件实例,而不是销毁它们。当组件在 <KeepAlive> 内切换时,其状态会被保留,避免重复渲染和数据丢失。

核心原理

  • 被缓存的组件会触发 activated(激活时)和 deactivated(失活时)两个生命周期钩子。
  • 不会缓存所有组件,可通过 include/exclude 精准控制缓存范围。

基础使用(组件切换缓存)

<template>
  <button @click="currentComp = 'CompA'">切换到A</button>
  <button @click="currentComp = 'CompB'">切换到B</button>

  <!-- KeepAlive 包裹动态组件 -->
  <KeepAlive>
    <component :is="currentComp" />
  </KeepAlive>
</template>

<script setup>
import { ref } from 'vue'
import CompA from './CompA.vue'
import CompB from './CompB.vue'

const currentComp = ref('CompA')
</script>

示例效果:CompA 中输入的表单内容,切换到 CompB 再切回 CompA 时,内容不会丢失。

关键属性

属性 作用 示例
include 只缓存名称匹配的组件(支持字符串、正则、数组) include="CompA,CompB" / :include="/^Comp/"
exclude 不缓存名称匹配的组件(优先级高于 include :exclude="['CompC']"
max 最大缓存组件实例数(超过则销毁最久未使用的) :max="3"

注意:组件名称需匹配 name 选项(SFC 中默认是文件名,也可手动在 <script> 中定义 name)。

生命周期钩子

<KeepAlive> 缓存的组件,不再触发 created/mounted(首次渲染会触发),而是触发:

  • activated:组件被激活(切回该组件时)
  • deactivated:组件被失活(切离该组件时)

4. teleport — 内容传送(Vue3 新增)

https://cn.vuejs.org/guide/built-ins/teleport.html

作用:将组件内的部分内容 “传送” 到指定的 DOM 节点下,解决层级遮挡问题(如弹窗、通知组件)。

示例:

<template>
  <teleport to="body">
    <div class="modal" v-if="isOpen">
      弹窗内容(DOM 结构会被移到 body 下)
    </div>
  </teleport>
</template>

<script setup>
import { ref } from 'vue'
const isOpen = ref(false)
</script>

关键注意点:

  • to 属性指定目标 DOM 节点,可传入选择器(如.container)或 DOM 元素;
  • 仅改变 DOM 结构,组件逻辑(如数据、事件)仍归属于父组件,不影响组件通信。

5. suspense — 异步状态管理(Vue3 新增)

作用:管理异步组件或异步操作的加载状态,提供加载占位符,提升用户体验。

示例:

<template>
  <suspense>
    <!-- default 插槽:异步目标内容(异步组件/含异步操作的组件) -->
    <template #default>
      <AsyncComponent />
    </template>
    <!-- fallback 插槽:加载中占位符 -->
    <template #fallback>
      <div>加载中...</div>
    </template>
  </suspense>
</template>

<script setup>
// 导入异步组件
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'))
</script>

关键注意点:

  • 需配合异步组件(defineAsyncComponent 定义)或组件内的异步操作(如 await 请求);
  • 暂不支持服务器端渲染(SSR),仅适用于客户端渲染场景。

总结

Vue3 内置指令可分为以下几类:

  • 渲染控制v-textv-htmlv-showv-if/v-elsev-for
  • 事件处理v-on@
  • 属性绑定v-bind:
  • 表单绑定v-model
  • 性能/编译控制v-prev-cloakv-once

这些指令覆盖了日常开发的大部分场景,通过简化 DOM 操作,使开发者更专注于数据逻辑而非 DOM 细节。

  • 核心功能实现

    • 文本/HTML渲染

      • 纯文本覆盖 → v-text

      • 插入HTML(仅可信内容,防XSS) → v-html

    • 元素显隐/条件渲染

      • 频繁切换(CSS display控制,DOM始终存在) → v-show

      • 少切换/多条件(动态创建/销毁DOM) → v-if/v-else-if/v-else(可配合

posted @ 2025-09-15 15:12  【唐】三三  阅读(51)  评论(0)    收藏  举报