vue入门:计算属性computer监听器watch
文章目录
- 计算属性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 属性来实现。