计算属性与监听器
计算属性
计算属性是基于它们的依赖进行缓存的属性,只有当依赖发生变化时,才会重新计算。
选项式 API 计算属性
export default {
data() {
return {
message: 'Hello',
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
// 基本计算属性
reversedMessage() {
return this.message.split('').reverse().join('')
},
// 完整写法,包含 getter 和 setter
fullName: {
get() {
return `${this.firstName} ${this.lastName}`
},
set(newValue) {
const [firstName, lastName] = newValue.split(' ')
this.firstName = firstName
this.lastName = lastName
}
}
}
}
组合式 API 计算属性
import { ref, computed } from 'vue'
export default {
setup() {
const message = ref('Hello')
const firstName = ref('John')
const lastName = ref('Doe')
// 基本计算属性
const reversedMessage = computed(() => {
return message.value.split('').reverse().join('')
})
// 完整写法,包含 getter 和 setter
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(newValue) {
const [firstNameValue, lastNameValue] = newValue.split(' ')
firstName.value = firstNameValue
lastName.value = lastNameValue
}
})
return {
message,
firstName,
lastName,
reversedMessage,
fullName
}
}
}
监听器
监听器用于监听数据变化并执行相应的副作用,如发送网络请求、更新 DOM 等。
选项式 API 监听器
export default {
data() {
return {
count: 0,
user: {
name: 'John',
age: 30
}
}
},
watch: {
// 基本监听
count(newValue, oldValue) {
console.log(`count 从 ${oldValue} 变为 ${newValue}`)
},
// 深度监听
user: {
handler(newValue, oldValue) {
console.log('user 对象发生变化', newValue, oldValue)
},
deep: true
},
// 立即执行
count: {
handler(newValue, oldValue) {
console.log(`count: ${newValue}`)
},
immediate: true
}
}
}
组合式 API 监听器
import { ref, reactive, watch } from 'vue'
export default {
setup() {
const count = ref(0)
const user = reactive({
name: 'John',
age: 30
})
// 监听 ref
watch(count, (newValue, oldValue) => {
console.log(`count 从 ${oldValue} 变为 ${newValue}`)
})
// 监听 reactive 对象
watch(user, (newValue, oldValue) => {
console.log('user 对象发生变化', newValue, oldValue)
}, { deep: true })
// 监听多个源
watch([count, () => user.age], ([newCount, newAge], [oldCount, oldAge]) => {
console.log(`count: ${newCount}, age: ${newAge}`)
})
// 立即执行
watch(count, (newValue) => {
console.log(`count: ${newValue}`)
}, { immediate: true })
return {
count,
user
}
}
}
watchEffect - 自动追踪依赖
import { ref, reactive, watchEffect } from 'vue'
export default {
setup() {
const count = ref(0)
const user = reactive({
name: 'John',
age: 30
})
// 自动追踪所有依赖
const stop = watchEffect(() => {
console.log(`count: ${count.value}, name: ${user.name}`)
})
// 停止监听
// stop()
return {
count,
user
}
}
}
计算属性 vs 方法
| 特性 | 计算属性 | 方法 |
|---|---|---|
| 缓存 | 基于依赖缓存,只有依赖变化才重新计算 | 每次调用都会重新执行 |
| 语法 | 作为属性使用,无需括号 | 作为函数调用,需要括号 |
| 适用场景 | 基于现有数据派生新数据 | 执行复杂逻辑或异步操作 |
计算属性 vs 监听器
| 特性 | 计算属性 | 监听器 |
|---|---|---|
| 用途 | 基于依赖派生新数据 | 监听数据变化执行副作用 |
| 缓存 | 有缓存机制 | 无缓存机制 |
| 语法 | 声明式 | 命令式 |
| 适用场景 | 数据转换、过滤、格式化 | 异步操作、DOM 更新、网络请求 |
最佳实践
- 优先使用计算属性处理数据派生,因为它有缓存机制,性能更好
- 使用监听器处理副作用,如发送网络请求、更新 DOM 等
- 对于简单的计算,使用方法可能更直观
- 使用 watchEffect 可以自动追踪依赖,减少代码量
- 避免在计算属性中执行异步操作或修改其他状态