文章目录
- 计算属性computer
- 定义计算属性
- 在模板中使用计算属性
- 计算属性的使用场景
- 监听器watch
- 基本语法
- 深度监听
- 立即执行
- 监听数组
- 异步操作
- 数据校验
- 副作用处理
- 清理监听器
- watch 与 computed 的区别
计算属性computer
在 Vue 中,计算属性(computed)是一种非常强大的功能,它允许你基于组件的响应式数据动态计算新的值。计算属性是基于它们的依赖进行缓存的,只有当依赖发生变化时,计算属性才会重新计算。这使得计算属性比普通的方法更加高效,尤其是在处理复杂逻辑或性能敏感的场景时。
Vue 的响应式系统会追踪计算属性的依赖。当计算属性的依赖发生变化时,计算属性会自动重新计算。依赖追踪是基于 Vue 的响应式系统实现的,它能够高效地检测依赖的变化
new Vue({el: '#app',data: {a: 1,b: 2},computed: {c() {return this.a + this.b;}}
});
在这个例子中,c 是一个计算属性,它依赖于 a 和 b。当 a 或 b 的值发生变化时,c 会自动重新计算。
定义计算属性
计算属性通过 computed 选项定义,它是一个对象,对象的每个属性对应一个计算逻辑。计算属性可以是一个函数,也可以是一个包含 get 和 set 方法的对象
new Vue({el: '#app',data: {firstName: 'John',lastName: 'Doe'},computed: {fullName() {return `${this.firstName} ${this.lastName}`;}}
});
fullName 是一个计算属性,它基于 firstName 和 lastName 的值动态计算出完整的姓名。当 firstName 或 lastName 发生变化时,fullName 会自动重新计算
在模板中使用计算属性
<div id="app"><p>First Name: <input v-model="firstName"></p><p>Last Name: <input v-model="lastName"></p><p>Full Name: {{ fullName }}</p>
</div>
计算属性的使用场景
- 数据格式化
new Vue({el: '#app',data: {date: new Date()},computed: {formattedDate() {return this.date.toISOString().split('T')[0];}}
});
formattedDate 是一个计算属性,它将 date 格式化为 YYYY-MM-DD 的格式。
- 复杂逻辑计算
new Vue({el: '#app',data: {items: [{ name: 'Item 1', price: 10, quantity: 2 },{ name: 'Item 2', price: 20, quantity: 3 }]},computed: {totalPrice() {return this.items.reduce((total, item) => total + item.price * item.quantity, 0);}}
});
totalPrice 是一个计算属性,它基于 items 数组计算购物车的总价。
- 条件渲染
new Vue({el: '#app',data: {user: {role: 'admin'}},computed: {isAdmin() {return this.user.role === 'admin';}}
});
isAdmin 是一个计算属性,它基于 user.role 的值动态计算用户是否为管理员
监听器watch
在 Vue 中,watch 是一个非常强大的功能,用于监听组件数据的变化,并在数据发生变化时执行特定的逻辑。与计算属性(computed)相比,watch 提供了更灵活的响应机制,可以执行更复杂的操作,包括异步操作和副作用。
watch 可以监听组件中的数据属性或计算属性,并在它们发生变化时执行回调函数。
基本语法
- 数据属性
new Vue({el: '#app',data: {message: 'Hello, Vue!',b: { c: 2, d: 3 },},watch: {message(newVal, oldVal) {console.log(`Message changed from ${oldVal} to ${newVal}`);},"b.c": function(val, oldVal) {this.b.d += 1;console.log("new: %s, old: %s", val, oldVal);},}
});
watch 监听了 message 属性。当 message 的值发生变化时,会调用回调函数,newVal 是新值,oldVal 是旧值。
- 计算属性
new Vue({el: '#app',data: {firstName: 'John',lastName: 'Doe'},computed: {fullName() {return `${this.firstName} ${this.lastName}`;}},watch: {fullName(newVal, oldVal) {console.log(`Full Name changed from ${oldVal} to ${newVal}`);}}
});
watch 监听了计算属性
fullName
。当firstName
或lastName
的值发生变化时,fullName
会重新计算,watch 会捕获到这个变化并执行回调函数。
深度监听
默认情况下,watch 是浅监听,只监听对象的第一层属性变化。如果需要监听对象的深层属性变化,可以使用 deep 选项。
new Vue({el: '#app',data: {user: {name: 'John',age: 30}},watch: {user: {handler(newVal, oldVal) {console.log(`User changed from ${JSON.stringify(oldVal)} to ${JSON.stringify(newVal)}`);},deep: true}}
});
watch 使用了
deep
选项来深度监听user
对象。当user
对象的任何属性(如 name 或 age
)发生变化时,都会触发回调函数.
立即执行
默认情况下,watch 的回调函数只有在监听的数据发生变化时才会执行。如果需要在组件初始化时立即执行回调函数,可以使用 immediate 选项.
new Vue({el: '#app',data: {message: 'Hello, Vue!'},watch: {message: {handler(newVal, oldVal) {console.log(`Message changed from ${oldVal} to ${newVal}`);},immediate: true}}
});
watch 使用了 immediate 选项。组件初始化时,message 的值会被传递给回调函数,即使它没有发生变化。
监听数组
watch 也可以监听数组的变化,但需要注意数组的响应式操作。
new Vue({el: '#app',data: {items: [1, 2, 3]},watch: {items: {handler(newVal, oldVal) {console.log(`Items changed from ${oldVal} to ${newVal}`);},deep: true}}
});
watch 监听了 items 数组。当数组的元素发生变化时,会触发回调函数。需要注意的是,
直接通过索引修改数组元素(如 this.items[0] = 4)不会触发响应式更新,应该使用 Vue 提供的数组方法(如 push, splice 等)来确保响应性。
watch 的应用场景
异步操作
new Vue({el: '#app',data: {userId: 1},watch: {userId(newVal, oldVal) {this.fetchUserData(newVal);}},methods: {fetchUserData(userId) {fetch(`https://api.example.com/users/${userId}`).then(response => response.json()).then(data => {console.log(data);});}}
});
当 userId 的值发生变化时,会调用 fetchUserData 方法从服务器获取用户数据。
数据校验
new Vue({el: '#app',data: {email: ''},watch: {email(newVal) {if (!this.validateEmail(newVal)) {alert('Invalid email address');}}},methods: {validateEmail(email) {const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;return re.test(email);}}
});
副作用处理
watch 可以用于处理副作用,例如在数据变化时更新 DOM 或调用第三方库。
new Vue({el: '#app',data: {count: 0},watch: {count(newVal) {document.title = `Count is ${newVal}`;}}
});
当 count 的值发生变化时,会更新浏览器的标题。
清理监听器
在组件销毁时,清理不必要的监听器,避免内存泄漏。
new Vue({el: '#app',data: {message: 'Hello, Vue!'},watch: {message: {handler(newVal, oldVal) {console.log(`Message changed from ${oldVal} to ${newVal}`);},immediate: true}},beforeDestroy() {this.$watchers.message.teardown();}
});
在这个例子中,使用 beforeDestroy 生命周期钩子清理了 message 的监听器。
watch 与 computed 的区别
- computed:基于依赖进行缓存,只有当依赖发生变化时才会重新计算。计算属性是同步的,适合用于简单的数据计算。
- watch:提供更灵活的响应机制,可以执行异步操作和副作用。watch 的回调函数在数据变化时立即执行,适合用于复杂的逻辑处理。
- 能使用计算属性 computed 实现的的,则尽量使用 computed 属性来实现。