一:计算属性 computed
- 1.1 模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。
export default {
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
}
}
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。
export default {
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
},
computed: {
// 一个计算属性的 getter
publishedBooksMessage() {
// `this` 指向当前组件实例
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
}
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
watch 选项也支持把键设置成用 . 分隔的路径:
export default {
watch: {
// 注意:只能是简单的路径,不支持表达式。
'some.nested.key'(newValue) {
// ...
}
}
}
- 1.2 可写计算属性
计算属性默认是只读的。当你尝试修改一个计算属性时,你会收到一个运行时警告。只在某些特殊场景中你可能才需要用到“可写”的属性,你可以通过同时提供 getter 和 setter 来创建:
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
// 注意:我们这里使用的是解构赋值语法
[this.firstName, this.lastName] = newValue.split(' ')
}
}
}
}
现在当你再运行 this.fullName = 'John Doe' 时,setter 会被调用而 this.firstName 和 this.lastName 会随之更新。
二:侦听器 watch
- 2.1 默认侦听
export default {
data() {
return {
name: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// 每当 question 改变时,这个函数就会执行
name(newQuestion, oldQuestion) {
this.getAnswer()
}
},
methods: {
getAnswer() {
this.answer = 'hello' + this.name
}
}
}
<p>
Ask yes name:
<input v-model="name" />
</p>
<p>{{ answer }}</p>
- 2.2 深层侦听器#
watch 默认是浅层的:被侦听的属性,仅在被赋新值时,才会触发回调函数——而嵌套属性的变化不会触发。如果想侦听所有嵌套的变更,你需要深层侦听器:
export default {
watch: {
someObject: {
handler(newValue, oldValue) {
// 若设置了 immediate: true 则 在组件实例创建时会立即调用
},
// deep 设置诶 true 为深层侦听
deep: true,
// 强制立即执行回调
immediate: true,
// 回调的触发时机
flush: 'post'
}
}
}
- 2.3 即时回调的侦听器
在侦听的属性里面设置 immediate: true , 代码如上。
- 2.4 回调的触发时机
- 默认情况下,用户创建的侦听器回调,都会在 Vue 组件更新之前被调用。这意味着你在侦听器回调中访问的 DOM 将是被 Vue 更新之前的状态。
如果想在侦听器回调中能访问被 Vue 更新之后的 DOM,你需要指明 flush: 'post' 选项:
在侦听的属性里面设置 flush: 'post' , 代码如上。
- 2.5
this.$watch()
我们也可以使用组件实例的 $watch() 方法来命令式地创建一个侦听器:
export default {
created() {
this.$watch('question', (newQuestion) => {
// ...
})
}
}
如果要在特定条件下设置一个侦听器,或者只侦听响应用户交互的内容,这方法很有用。它还允许你提前停止该侦听器。
- 2.6 停止侦听器
const unwatch = this.$watch('foo', callback)
// ...当该侦听器不再需要时
unwatch()
代码
<template>
<div>
<input v-model="firstName" />
<br/>
<input v-model="lastName" />
<br/>
fullName: {{fullName}}
<button @click="unWatch"> unWatch </button>
</div>
</template>
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
console.log('newValue', newValue)
}
}
},
mounted(){
this.unwatchHanndler = this.$watch('fullName', callback)
},
methods: {
callback(){
console.log('callback')
},
unWatch(){
this.unwatchHanndler()
},
}
}
将watch赋值给一个变量,当达到条件调用watch赋值的那个变量就可以终止监听了。
2.7 是否可以认为 写在 watch 里面的侦听由于没有赋值,不可以终止侦听?
三:计算属性 computed VS 侦听器 watch
-
计算属性 注重
变化结果,其他属性变化导致了该计算属性变化。 -
侦听器 注重
变化过程, 侦听的属性变化时要做什么事件。