六、类与样式绑定

绑定 class

<!-- 对象语法 -->
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<div class="static" :class="{ active: isActive }"></div>  <!-- 可与静态 class 共存 -->

<!-- 数组语法 -->
<div :class="[activeClass, errorClass]"></div>
<div :class="[isActive ? activeClass : '', errorClass]"></div>
<div :class="[{ [activeClass]: isActive }, errorClass]"></div>

<!-- 绑定 reactive/computed 对象 -->
<div :class="classObject"></div>
const classObject = reactive({ active: true, 'text-danger': false })
const classObject = computed(() => ({
  active: isActive.value && !error.value,
  'text-danger': error.value && error.value.type === 'fatal'
}))

绑定内联样式

<!-- 对象语法 -->
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<div :style="styleObject"></div>

<!-- 数组语法 -->
<div :style="[baseStyles, overridingStyles]"></div>

<!-- 样式多值(仅渲染浏览器支持的最后一个) -->
<div :style="{ display: ['-webkit-box', 'flex'] }"></div>
const styleObject = reactive({ color: 'red', fontSize: '30px' })
  • :style 支持 camelCase 和 kebab-cased CSS 属性名
  • Vue 自动为需要浏览器前缀的 CSS 属性添加前缀
  • 单根元素组件上设置的 class 会自动合并到根元素

七、条件渲染

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

<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>Not A/B</div>
  • v-else / v-else-if 必须紧跟在 v-ifv-else-if 后面

<template> 上的 v-if

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

<template> 是不可见包装器,渲染结果不包含自身。

v-show

<h1 v-show="ok">Hello!</h1>

v-if vs v-show

特性 v-if v-show
初始条件为 false 不渲染(惰性) 仍渲染,display: none
切换行为 销毁和重建 切换 CSS display
切换开销
初始渲染开销
适用场景 条件很少改变 频繁切换

v-show 不支持 <template>v-elsev-ifv-for 同时存在时不推荐。


八、列表渲染

基本用法

<!-- 遍历数组 -->
<li v-for="item in items">{{ item.message }}</li>
<li v-for="(item, index) in items">{{ index }} - {{ item.message }}</li>
<li v-for="{ message } in items">{{ message }}</li>

<!-- 遍历对象 -->
<li v-for="(value, key, index) in myObject">{{ index }}. {{ key }}: {{ value }}</li>

<!-- 遍历范围(从 1 开始) -->
<span v-for="n in 10">{{ n }}</span>

通过 key 管理状态

<div v-for="item in items" :key="item.id">{{ item.name }}</div>
  • :key 必须是字符串或数字,不能是对象
  • 不提供 key 时 Vue 使用"就地更新"策略,可能导致状态错乱

数组变化侦测

变更方法(自动追踪):pushpopshiftunshiftsplicesortreverse

替换数组(非变更方法需替换整个数组):

numbers.value = numbers.value.filter(n => n % 2 === 0)

展示过滤或排序后的结果

使用 computed 而非方法,避免每次渲染都重新计算:

const numbers = ref([1, 2, 3, 4, 5])
const evenNumbers = computed(() => numbers.value.filter(n => n % 2 === 0))

reverse()sort() 会修改原数组。在 computed 中需先拷贝:return [...numbers].reverse()


九、事件处理

内联与方法处理器

<button @click="count++">Add 1</button>                   <!-- 内联 -->
<button @click="greet">Greet</button>                      <!-- 方法 -->
<button @click="say('hello')">Say hello</button>            <!-- 内联调用方法 -->
<button @click="warn('msg', $event)">Submit</button>        <!-- 传递原生事件 -->
<button @click="(e) => warn('msg', e)">Submit</button>      <!-- 箭头函数 -->

事件修饰符

<a @click.stop="doThis"></a>               <!-- 阻止冒泡 -->
<form @submit.prevent="onSubmit"></form>    <!-- 阻止默认行为 -->
<a @click.stop.prevent="doThat"></a>        <!-- 链式调用 -->
<div @click.self="doThat"></div>            <!-- 仅自身触发 -->
<div @click.capture="doThis"></div>         <!-- 捕获模式 -->
<a @click.once="doThis"></a>                <!-- 只触发一次 -->
<div @scroll.passive="onScroll"></div>      <!-- 被动监听 -->

不要 同时使用 .passive.prevent。修饰符顺序影响行为:@click.prevent.self vs @click.self.prevent

按键修饰符

<input @keyup.enter="submit" />
<input @keyup.page-down="onPageDown" />
<input @keyup.alt.enter="clear" />          <!-- 组合键 -->
<div @click.ctrl="doSomething"></div>
<button @click.ctrl.exact="onClick">A</button>  <!-- 精确匹配 -->

鼠标按键修饰符

.left.right.middle


十、表单输入绑定

基本用法

<input v-model="message" placeholder="edit me" />
<textarea v-model="message"></textarea>

<!-- 复选框:单个布尔值 / 多选数组 -->
<input type="checkbox" v-model="checked" />
<input type="checkbox" value="Jack" v-model="checkedNames" />

<!-- 单选 -->
<input type="radio" value="One" v-model="picked" />

<!-- 选择器 -->
<select v-model="selected">
  <option disabled value="">请选择</option>
  <option>A</option>
  <option>B</option>
</select>

动态选择器选项

<select v-model="selected">
  <option v-for="option in options" :value="option.value">
    {{ option.text }}
  </option>
</select>

值绑定

<!-- 复选框自定义 true/false 值 -->
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
<input type="checkbox" v-model="toggle" :true-value="dynamicTrue" :false-value="dynamicFalse" />

修饰符

<input v-model.lazy="msg" />    <!-- 在 'change' 事件后同步,而非 'input' -->
<input v-model.number="age" />   <!-- 自动转为数字 -->
<input v-model.trim="msg" />     <!-- 自动去除首尾空格 -->

注意事项:

  • v-model 忽略 HTML 初始 value/checked/selected,应在 JS 中声明初始值
  • <textarea> 不支持插值 {{ text }},必须用 v-model
  • CJK 输入法组合期间 v-model 不会更新
  • type="number".number 自动生效;清空输入返回空字符串(非 null)

更多推荐