Vue中watch和computed的区别
Vue中watch和computed的区别
YuXiangVue2 中 watch 和 computed 的区别与使用指南
在 Vue2 中,watch 和 computed 都是用于监听数据变化并执行相应操作的 API,但它们在用法和适用场景上存在一些区别。
1. 定义
- watch: 监听一个特定的数据变化,并在变化时执行回调函数。
- computed: 根据依赖的数据动态计算出一个新的值,并缓存计算结果,只有当依赖的数据发生变化时才会重新计算。
2. 特点
特性 | watch | computed |
---|---|---|
监听方式 | 监听特定的数据变化 | 监听依赖的数据变化 |
返回值 | 无返回值 | 返回计算后的值 |
缓存 | 无缓存 | 有缓存 |
异步 | 支持异步操作 | 不支持异步操作 |
适用场景 | 数据变化时执行异步操作或复杂逻辑 | 根据数据动态计算新的值 |
3. 使用场景
watch 的使用场景
异步操作
当需要在数据变化时执行异步操作(例如 API 请求)时,watch 是最佳选择。例如:1
2
3
4
5watch: {
searchQuery(newVal) {
this.fetchData(newVal); // 当 searchQuery 变化时,触发 API 请求
}
}复杂逻辑
当数据变化时需要执行一系列复杂的逻辑操作时,watch 可以更好地组织代码。例如:1
2
3
4
5
6
7
8
9
10watch: {
user(newVal) {
if (newVal.age > 18) {
this.isAdult = true;
this.checkEligibility();
} else {
this.isAdult = false;
}
}
}监听路由变化
在 Vue Router 中,可以使用 watch 监听路由参数的变化,例如:1
2
3
4
5watch: {
'$route.params.id'(newVal) {
this.loadUserData(newVal); // 当路由参数 id 变化时,加载用户数据
}
}深度监听
当需要监听对象或数组内部的变化时,可以使用deep
选项:1
2
3
4
5
6
7
8watch: {
user: {
handler(newVal) {
console.log('user 对象发生变化');
},
deep: true // 深度监听
}
}
computed 的使用场景
动态计算属性
当需要根据其他数据动态计算出一个新值时,computed 是最佳选择。例如:1
2
3
4
5computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}过滤或排序列表
在需要对列表进行过滤或排序时,computed 可以很方便地实现:1
2
3
4
5computed: {
filteredList() {
return this.list.filter(item => item.price > 100);
}
}依赖多个数据
当计算属性依赖于多个数据时,computed 会自动追踪依赖,并在任一依赖变化时重新计算:1
2
3
4
5computed: {
totalPrice() {
return this.quantity * this.unitPrice;
}
}缓存优化性能
computed 的缓存机制可以避免重复计算,提升性能。例如:1
2
3
4
5
6
7
8
9
10computed: {
expensiveCalculation() {
// 假设这是一个耗时的计算
let result = 0;
for (let i = 0; i < 1000000; i++) {
result += i;
}
return result;
}
}
4. 注意事项
watch 的注意事项
避免过度使用
如果过度使用 watch,可能会导致代码难以维护。对于简单的数据变化,优先考虑使用 computed。监听引用类型时的陷阱
监听对象或数组时,如果直接修改引用类型的属性(例如this.user.name = 'newName'
),watch 可能不会触发。此时需要使用deep: true
或使用Vue.set
方法。立即执行
如果需要在监听器创建时立即执行一次回调,可以使用immediate: true
:1
2
3
4
5
6
7
8watch: {
user: {
handler(newVal) {
console.log('user 发生变化');
},
immediate: true
}
}
computed 的注意事项
避免副作用
computed 应该是纯函数,不应该有副作用(例如修改数据或触发异步操作)。依赖追踪
computed 只会追踪在计算函数中使用的响应式数据。如果依赖的数据没有在函数中使用,computed 不会更新。缓存机制
computed 的缓存是基于依赖的。如果依赖没有变化,即使多次访问 computed 属性,也不会重新计算。
5. 高级用法
watch 的高级用法
监听多个数据
可以使用数组监听多个数据:1
2
3
4
5watch: {
['data1', 'data2'](newVal, oldVal) {
console.log('data1 或 data2 发生变化');
}
}监听器卸载
在组件销毁时,可以手动卸载监听器:1
2
3
4
5
6created() {
this.unwatch = this.$watch('data', this.handler);
},
beforeDestroy() {
this.unwatch(); // 手动卸载监听器
}
computed 的高级用法
setter 函数
computed 可以定义 setter 函数,允许对计算属性赋值:1
2
3
4
5
6
7
8
9
10
11
12computed: {
fullName: {
get() {
return this.firstName + ' ' + this.lastName;
},
set(newVal) {
const names = newVal.split(' ');
this.firstName = names[0];
this.lastName = names[1];
}
}
}依赖非响应式数据
如果 computed 依赖的数据不是响应式的,可以使用Vue.set
或this.$set
将其转换为响应式数据。
6. 总结对比表格
特性 | watch | computed |
---|---|---|
定义 | 监听特定数据变化,执行回调函数 | 根据依赖数据动态计算新值,并缓存结果 |
返回值 | 无 | 有 |
缓存 | 无 | 有 |
异步支持 | 支持 | 不支持 |
适用场景 | 数据变化时执行异步操作或复杂逻辑 | 根据数据动态计算新的值 |
性能 | 无缓存,可能重复执行 | 有缓存,性能更优 |
深度监听 | 支持(需配置 deep: true ) |
不支持 |
立即执行 | 支持(需配置 immediate: true ) |
不支持 |
setter 函数 | 不支持 | 支持 |