Options API:响应式基础
约 881 字大约 3 分钟
布欧-Lewyon
2026-05-15
首页 › Vue › Vue 基础 › Options API:响应式基础
Options API 是 Vue 2 时代就存在的 API 风格。Vue 3 完全兼容它,同时新增了 Composition API。先从最熟悉的 Options API 开始。
核心选项
<script>
export default {
name: 'Counter', // 组件名称(DevTools 显示用)
data() { // ⭐ 响应式数据
return {
count: 0,
user: { name: 'Alice', age: 25 },
tags: ['vue', 'react']
}
},
methods: { // ⭐ 方法
increment(n) {
this.count += n
},
greet() {
alert(`Hello, ${this.user.name}`)
}
},
computed: { // ⭐ 计算属性(缓存)
double() {
return this.count * 2
},
greeting() {
return this.count > 0 ? `已点击 ${this.count} 次` : '未点击'
}
},
watch: { // ⭐ 监听器
count(newVal, oldVal) {
console.log(`count 从 ${oldVal} 变为 ${newVal}`)
},
'user.name': function(val) {
console.log('用户名变了:', val)
},
tags: { // 深度监听
handler(val) { console.log('tags 变化:', val) },
deep: true
}
}
}
</script>data:响应式数据
data 返回的对象会被 Vue 递归转为响应式(Vue 3 用 Proxy实现)。
<script>
export default {
data() {
return {
count: 0,
items: ['a', 'b']
}
},
methods: {
mutate() {
this.count++ // ✅ 响应式
this.items[2] = 'c' // ✅ Vue 3 支持数组索引
delete this.items[0] // ✅ Vue 3 支持属性删除
this.user = { ...this.user } // ✅ 替换整个对象也触发
}
}
}
</script>Vue 2 用
Object.defineProperty,无法检测数组索引赋值和属性新增/删除,需要Vue.set()和$set。Vue 3 用Proxy,不再有这些限制。
methods:方法
methods 中的函数自动绑定到组件实例,可以在模板中直接调用:
<template>
<p>{{ count }}</p>
<button @click="increment(1)">+1</button>
<button @click="increment(5)">+5</button>
</template>注意:不要用箭头函数定义 methods(
increment: () => { ... }),否则this不会指向组件实例。
computed:计算属性
计算属性基于依赖缓存,只有依赖变化时才重新计算:
<template>
<p>{{ double }}</p> <!-- 第一次计算并缓存 -->
<p>{{ double }}</p> <!-- 直接读缓存,不重新计算 -->
<p>{{ double }}</p> <!-- 同上 -->
</template>计算属性 vs 方法
<script>
export default {
data: () => ({ items: [1, 2, 3, 4, 5] }),
computed: {
evenItems() { // ⭐ 缓存,依赖 items 不变则不重算
return this.items.filter(i => i % 2 === 0)
}
},
methods: {
getEvenItems() { // ❌ 每次访问都重新计算
return this.items.filter(i => i % 2 === 0)
}
}
}
</script>可写计算属性
计算属性默认只读。可以通过 getter / setter 实现"可写":
<script>
export default {
data: () => ({ firstName: 'John', lastName: 'Doe' }),
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`
},
set(val) {
const parts = val.split(' ')
this.firstName = parts[0]
this.lastName = parts[1] || ''
}
}
}
}
</script>watch:监听器
当需要在数据变化时执行异步或开销较大的操作时使用 watch:
<script>
export default {
data: () => ({ query: '', results: [] }),
watch: {
// 基础用法:新值、旧值
query(newVal, oldVal) {
this.debouncedSearch(newVal)
},
// 立即执行(immediate)
query: {
handler: 'fetchResults',
immediate: true
},
// 深度监听
user: {
handler(val) { /* val 整个对象变化时触发 */ },
deep: true // 监听嵌套属性变化
}
},
methods: {
fetchResults(q) { /* API 请求 */ },
debouncedSearch: debounce(function(q) { this.fetchResults(q) }, 300)
}
}
</script>watch 选项
| 选项 | 作用 |
|---|---|
deep: true | 深度监听对象内部变化 |
immediate: true | 初始化时立即执行一次 handler |
flush: 'post' | DOM 更新后执行(默认) |
flush: 'sync' | 数据变化时同步执行 |
完整的 Options API 组件
<script>
export default {
data() {
return { count: 0, step: 1 }
},
computed: {
display() {
return `当前值: ${this.count}`
}
},
watch: {
count(val) {
document.title = `计数: ${val}`
}
},
methods: {
increment() { this.count += this.step }
},
// 生命周期(下一节详解)
mounted() {
console.log('组件已挂载')
}
}
</script>
<template>
<p>{{ display }}</p>
<input type="number" v-model.number="step" />
<button @click="increment">加 {{ step }}</button>
</template>小结
| 选项 | 作用 | 特性 |
|---|---|---|
data | 定义响应式数据 | 返回对象,自动递归响应式 |
methods | 定义方法 | 自动绑 this,模板可直接调用 |
computed | 计算属性 | 基于依赖缓存,只读/可写 |
watch | 监听器 | 支持 deep、immediate、异步场景 |
上一节:模板语法与指令 下一节:事件处理与条件/列表渲染
