我们知道,在Vue中,可以通过一个计算属性和watch函数来监听某个数据属性的变化,但这两者有一定的差别。在这里就做一下简要探讨。
1、计算属性适用的情形
我们可能会有这样的需求,一个数据属性在它所依赖的属性发生变化时,也要发生变化,这种情况下,我们最好使用计算属性。
例如在下面这个例子中,如果我们使用监听函数,代码就会变得有点冗余。
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
fullName
属性依赖于firstName
和lastName
,这里有个缺点就是,无论firstName
或lastName
其中的任何一个发生改变时,都要调用不同的监听函数来更新fullName
属性。但是当我们使用计算属性时,代码就会变得更加简洁。
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
这时,我们只要监听fullName
属性就行,至于firstName
或lastName
属性的任何改变,我们都可以通过fullName
的getter()
方法得到最终的fullName
值。
另外需要注意的是,计算属性可以同时设置getter()
、setter()
方法。例如:
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
2、监听器watch适当的情形
watch
函数适用于,当数据发生变化时,执行异步操作或较大开销操作的情况。来看下面的例子:
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script> var watchExampleVM = new Vue({ el: '#watch-example', data: { question: '', answer: 'I cannot give you an answer until you ask a question!' }, watch: { // 如果 `question` 发生改变,这个函数就会运行 question: function (newQuestion, oldQuestion) { this.answer = 'Waiting for you to stop typing...' this.getAnswer() } }, methods: { // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。 // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率 // AJAX 请求直到用户输入完毕才会发出。 function () { if (this.question.indexOf('?') === -1) { this.answer = 'Questions usually contain a question mark. ;-)' return } this.answer = 'Thinking...' var vm = this axios.get('https://yesno.wtf/api') .then(function (response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function (error) { vm.answer = 'Error! Could not reach the API. ' + error }) }, // 这是我们为判定用户停止输入等待的毫秒数 500 ) } }) </script>
在这个例子中,当question
数据属性发生改变时,就会调用getAnswer()
方法。该方法被调用后,会执行一个异步请求。最终将得到的结果赋给answer
属性。这是计算属性所代替不了的。