在 Vue 开发中,Methods、Computed 和 watch 是处理数据逻辑与交互的核心工具。很多初学者容易混淆三者的用法,尤其是在 Vue2 选项式 API 与 Vue3 组合式 API 的差异下,更需要明确它们的定位与适用场景。本文将从概念、用法(含 Vue2 与 Vue3 对比)、核心区别三个维度展开,结合代码实例帮你彻底理清思路。
一、基础概念与核心特性
在深入代码前,先通过一句话明确三者的核心定位:
-
Methods:普通方法,需主动调用,无缓存,每次调用都会重新执行逻辑;
-
Computed:计算属性,依赖数据变化自动更新,有缓存,仅依赖项改变时才重新计算;
-
watch:监听器,监听指定数据变化,触发自定义回调,可处理异步或复杂逻辑。
二、分场景解析:Vue2 vs Vue3 代码实例
1. Methods:主动触发的 “工具函数”
Methods 是 Vue 实例中定义的普通函数,主要用于处理用户交互(如点击事件)或重复使用的逻辑,必须通过 “调用” 执行(如@click="handleClick"
或this.handleFn()
),且每次调用都会重新执行内部代码,无缓存机制。
Vue2 选项式 API 用法
<template>
<div>
<button @click="calcSum">计算1-100的和</button>
<p>结果:{{ sum }}</p>
</div>
</template>
<script>
export default {
data() {
return {
sum: 0
};
},
methods: {
// 定义方法,需通过点击事件触发
calcSum() {
this.sum = Array.from({ length: 100 }, (_, i) => i + 1).reduce((a, b) => a + b, 0);
}
}
};
</script>
Vue3 组合式 API 用法(setup 语法糖)
Vue3 中无需在methods
选项中定义,直接在setup
(或语法糖脚本)中声明函数即可,调用方式与 Vue2 一致:
<template>
<div>
<button @click="calcSum">计算1-100的和</button>
<p>结果:{{ sum }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const sum = ref(0);
// 直接定义函数,作用等同于Vue2的Methods
const calcSum = () => {
sum.value = Array.from({ length: 100 }, (_, i) => i + 1).reduce((a, b) => a + b, 0);
};
</script>
2. Computed:依赖驱动的 “智能计算”
Computed(计算属性)是基于依赖数据动态生成结果的属性,核心优势是 “缓存”—— 只要依赖的数据源不变化,多次访问 Computed 属性会直接返回缓存结果,避免重复计算,提升性能。此外,Computed 支持 “读写” 两种模式(默认是只读)。
Vue2 选项式 API 用法(只读与可写)
<template>
<div>
<!-- 只读:依赖firstName和lastName自动生成全名 -->
<p>全名:{{ fullName }}</p>
<!-- 可写:修改fullName时拆分到firstName和lastName -->
<input v-model="fullName" placeholder="输入全名(如:张三)">
<p>拆分结果:{{ firstName }} - {{ lastName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '张',
lastName: '三'
};
},
computed: {
// 1. 只读计算属性(简写,仅getter)
// fullName() {
// return this.firstName + this.lastName;
// },
// 2. 可写计算属性(含getter和setter)
fullName: {
get() {
return this.firstName + this.lastName;
},
set(newVal) {
// 输入“李四”时,拆分出firstName=“李”,lastName=“四”
const [first, last] = newVal.split('');
this.firstName = first || '';
this.lastName = last || '';
}
}
}
};
</script>
Vue3 组合式 API 用法(computed 函数)
Vue3 中需通过computed
函数创建计算属性,支持传入 “函数”(只读)或 “对象”(可写),返回的是响应式对象,访问时需通过.value
(模板中无需):
<template>
<div>
<p>全名:{{ fullName }}</p>
<input v-model="fullName" placeholder="输入全名(如:张三)">
<p>拆分结果:{{ firstName }} - {{ lastName }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const firstName = ref('张');
const lastName = ref('三');
// 1. 只读计算属性(传入函数)
// const fullName = computed(() => firstName.value + lastName.value);
// 2. 可写计算属性(传入对象)
const fullName = computed({
get() {
return firstName.value + lastName.value;
},
set(newVal) {
const [first, last] = newVal.split('');
firstName.value = first || '';
lastName.value = last || '';
}
});
</script>
3. watch:数据变化的 “监听者”
watch(监听器)用于监听指定响应式数据的变化,当数据改变时触发回调函数,可处理异步逻辑(如接口请求)或复杂副作用(如操作 DOM)。Vue2 与 Vue3 的 watch 用法差异较大,尤其是 Vue3 新增了watchEffect
(自动追踪依赖)。
Vue2 选项式 API 用法(基础监听、深度监听、立即执行)
<template>
<div>
<input v-model="username" placeholder="输入用户名">
<div>用户信息:{{ userInfo.name }} - {{ userInfo.age }}</div>
</div>
</template>
<script>
export default {
data() {
return {
username: '',
userInfo: { name: '', age: 0 }
};
},
watch: {
// 1. 监听基本类型(如username)
username(newVal, oldVal) {
console.log('用户名变化:', oldVal, '→', newVal);
// 模拟异步请求:根据用户名获取用户信息
setTimeout(() => {
this.userInfo = { name: newVal, age: 20 + Math.floor(Math.random() * 10) };
}, 500);
},
// 2. 监听对象(需开启深度监听,否则仅对象引用变化才触发)
userInfo: {
handler(newVal) {
console.log('用户信息变化:', newVal);
},
deep: true, // 深度监听对象内部属性变化
immediate: true // 初始渲染时立即执行一次回调
},
// 3. 监听对象的单个属性(通过字符串路径)
'userInfo.name'(newVal) {
console.log('用户名单独变化:', newVal);
}
}
};
</script>
Vue3 组合式 API 用法(watch 函数 + watchEffect)
Vue3 中通过watch
函数监听数据,支持监听 “单个数据”“多个数据”“对象(需深度监听)”,同时新增watchEffect
(无需指定监听源,自动追踪依赖):
<template>
<div>
<input v-model="username" placeholder="输入用户名">
<div>用户信息:{{ userInfo.name }} - {{ userInfo.age }}</div>
</div>
</template>
<script setup>
import { ref, reactive, watch, watchEffect } from 'vue';
const username = ref('');
const userInfo = reactive({ name: '', age: 0 });
// 1. 监听基本类型(ref对象)
watch(username, (newVal, oldVal) => {
console.log('用户名变化:', oldVal, '→', newVal);
setTimeout(() => {
userInfo.name = newVal;
userInfo.age = 20 + Math.floor(Math.random() * 10);
}, 500);
});
// 2. 监听 reactive 对象(默认深度监听,无需写deep: true)
watch(userInfo, (newVal) => {
console.log('用户信息变化:', newVal);
}, { immediate: true }); // 立即执行
// 3. 监听对象的单个属性(需用函数返回)
watch(() => userInfo.name, (newVal) => {
console.log('用户名单独变化:', newVal);
});
// 4. 监听多个数据(数组形式)
watch([username, () => userInfo.age], ([newName, newAge], [oldName, oldAge]) => {
console.log('用户名或年龄变化:', newName, newAge);
});
// 5. 新增 watchEffect(自动追踪依赖,无需指定监听源)
// 当 username 或 userInfo 变化时,自动执行
watchEffect(() => {
console.log('watchEffect 触发:', username.value, userInfo.name);
});
</script>
注意:Vue3 中
watch
监听
ref
对象时直接传变量(如
username
),监听
reactive
对象的单个属性时需用 “函数返回”(如
() => userInfo.name
),否则无法正确追踪。
三、三者核心区别对比
通过表格清晰对比 Methods、Computed、watch 的关键差异,帮你快速选择适用场景:
对比维度 | Methods | Computed | watch |
---|---|---|---|
缓存机制 | 无缓存,每次调用重新执行 | 有缓存,依赖变化才更新 | 无缓存,数据变化就触发 |
触发方式 | 需主动调用(如事件、函数调用) | 依赖数据变化自动触发 | 监听数据变化自动触发 |
返回值 | 可返回任意值,也可无返回 | 必须返回一个值(作为属性使用) | 无返回值,仅执行回调逻辑 |
适用场景 | 处理用户交互、重复逻辑 | 数据计算(如拼接、过滤) | 异步操作、复杂副作用(如接口请求、DOM 操作) |
依赖追踪 | 无依赖追踪,调用即执行 | 自动追踪依赖数据 | 需手动指定监听源(watchEffect 自动追踪) |
Vue3 差异 | 直接定义函数,无选项 | 通过computed 函数创建 | 通过watch /watchEffect 函数创建,支持多数据监听 |
四、总结:如何选择?
-
当需要处理用户点击、表单提交等交互逻辑,或需要重复调用某段代码时,用Methods;
-
当需要基于现有数据生成新数据(如拼接姓名、过滤列表),且希望利用缓存提升性能时,用Computed;
-
当需要在数据变化时执行异步操作(如根据 ID 请求接口)或复杂副作用(如修改 DOM、日志上报)时,用watch;
-
Vue3 中若需自动追踪依赖(无需手动指定监听源),优先用watchEffect。
掌握三者的区别与适用场景,能让你的 Vue 代码更高效、更易维护。建议结合实际项目多练习,逐步形成 “按需选择” 的思维习惯。