1.watch 和 computed 的作用和区别
watch(侦听器)
-
作用: 监听器允许开发者自定义一个函数来观察 Vue 实例上的特定数据属性的变化,当这些属性发生变化时,会触发相应的回调函数。
-
特点:
- 非缓存:每次指定数据发生变化时都会立即执行监听函数。
- 灵活性:不仅可以监听单个属性,还可以监听对象或数组的所有属性变化。
- 深度监听:可以配置为深度监听,即监听嵌套对象内部属性的变化。
- 异步支持:监听器可以异步执行,这对于处理复杂的副作用或者异步操作非常有用。
-
应用场景:
- 在某个数据属性变化时需要执行额外的操作,如数据格式化、API 请求、组件间通信等。
- 执行副作用较大的计算,比如计算完成后再去更新另一个数据源。
// 示例代码 export default {data() {return {userInput: '',};},watch: {userInput(newValue, oldValue) {console.log('User input has changed from', oldValue, 'to', newValue);// 可能还会在这里进行进一步的处理,例如调用 API、过滤输入等},deepWatch: {handler: function (val) { /* ... */ },deep: true, // 深度监听},}, };
computed(计算属性)
-
作用: 计算属性是用来根据其他响应式属性值进行计算并返回结果的属性。当依赖于它的任何响应式属性发生变化时,它会自动重新计算,并更新到视图中。
-
特点:
- 缓存机制:计算属性具有缓存功能,只有在其依赖的响应式属性发生改变时才会执行计算逻辑。
- 简洁声明:通过一个getter函数来定义计算属性,无需手动监听或触发更新。
- 只读性:默认情况下,计算属性仅支持getter,不支持setter。这意味着你不能直接修改计算属性的值,只能通过修改其依赖的原始数据来间接影响其值。
-
应用场景:
- 当你需要基于一些复杂表达式或其他数据属性生成一个新的衍生状态时。
- 优化性能,避免在模板中做过多的数据绑定和重复计算。
// 示例代码
export default {data() {return {firstName: 'John',lastName: 'Doe',};},computed: {fullName() {return `${this.firstName} ${this.lastName}`;},},
};
2. 什么情况下应该使用 watch?
使用 watch(侦听器)的情况:
-
当需要在特定数据变化后执行额外的操作: 当某个数据变化时需要触发一些非简单的、带有副作用的操作,如调用API、更新DOM、更改路由、发送事件等。
-
需要监听深层次对象的变化: 若要深度监听一个对象或数组内部属性的变化,应使用
watch
并设置deep: true
选项。 -
手动控制执行时机或频率: 可以通过配置
immediate: true
来让回调在绑定时立即执行一次,或者根据条件决定是否执行回调逻辑。 -
针对特定数据变化的异步操作: 如果你需要在数据变化后执行异步任务,
watch
更适合这种场景,因为它允许你编写异步回调函数。watch: {searchQuery: function(newVal, oldVal) {if (newVal !== oldVal) {this.fetchDataFromAPI(newVal); // 在搜索查询变化时发起API请求}},deepWatch: {handler(newValue) { /* ... */ },deep: true,}, },
3. 什么情况下应该使用 computed
?
使用 computed(计算属性)的情况:
-
当需要基于其他状态或数据派生出新的状态时: 计算属性非常适合用于创建那些依赖于组件内部其他数据属性值进行计算,并且结果是可复用的状态。
-
当你希望自动缓存计算结果: 如果一个值的计算过程复杂或者耗时,而其依赖项没有改变的情况下多次获取该值时,应该使用计算属性。因为计算属性会自动缓存结果,只有在其依赖的数据发生变化时才会重新计算。
-
表达式可以简洁地定义为纯函数: 计算属性通常由一个返回值的getter方法组成,它仅根据输入(依赖的响应式数据)产生输出,不涉及副作用操作。
computed: {fullName() {return this.firstName + ' ' + this.lastName;}, }