今日学习目录
一、 计算属性computed
- 例子
- 计算属性缓存 vs 方法
- 计算属性 vs 侦听属性
- 计算属性的 setter
二、侦听器watch
- vm.$watch( expOrFn, callback, [options] )
开始今日学习
一、计算属性
设计初衷:在模板中放入表达式非常便捷用于简单运算,但是放入过多会导致模板逻辑过重和难于维护,例如
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
因此,对于任何复杂逻辑,建议使用计算属性。
1. 例子
<div id="example">
<p> Original message is : {{message}} </p>
<p> Computed reversed message: {{reversedMessage}} </p>
</div>
var vm = new Vue({
el: 'example',
data: {
message: 'hello'
},
computed: {
//计算属性的getter
reversedMessage: function() {
return this.message.split('').reverse().join('');
}
}
});
```
这里我们提供一个计算属性reversedMessage。我们提供的函数将用作vm.reversedMessage的getter函数
console.log(vm.reversedMessage); // 0lleh
vm.message = 'good';
console.log(vm.reversedMessage); //doog
``
vm.reversedMessage的值始终取决于vm.message的值
2. 计算属性缓存 VS 方法
同样的,我们可以在表达式当中去达到同样的效果
<p> {{ reversedMessage() }} </p>
methods: {
reversedMessage: function() {
return this.message.split('').reverse().join('')
}
}
通过上述这样,我们将同一个函数定义成一个方法,而不是一个计算属性。这两种防范的最终结果是完全相同的。然而,它的执行机制确是不同的。
计算属性是基于它们的依赖进行缓存的。
计算属性只有在它的相关属性发生改变的情况下,才会重新计算值,这就意味着,只要message没有发生改变,那么无论多次访问reversedMessage,计算属性会立即返回之前的计算结果,而不会重新运行函数。
同样,这也意味着下述计算属性将不会再更新,因为Data.now()不是响应式依赖
computed: {
now: function() {
return Data.now();
}
}
3. 计算属性 VS 监听属性
Vue还提供了一种更通用的方式来监听Vue实例上数据的变动:监听属性。
当然,通常更好的办法是使用计算属性而不是命令式的watch回调
<div id = "example">
{{ fullname }}
</div>
var vm = new Vue({
el: 'example',
data: {
firstname: 'Jack',
lastname: 'Lose',
fullname: 'Mark'
},
watch: {
firstname: function(val) {
this.fullname = val + ' ' + this.lastname;
}
lastname: function(val) {
this.fullname = this.firstname + ‘ ’ + val;
}
}
});
通过上述代码与计算属性代码对比发现,代码重复且繁琐。
3. 计算属性的setter
计算属性默认提供了getter,当我们在一些情况需要setter的时候 我们可以自己提供一个setter
computed: {
fullname: {
get: function() {
return this.firstname+ ' ' + this.lastname;
}
set : function(newValue) {
var names = newValue.split(' ');
this,firstname = names[0];
this.lastname = names[names.length - 1];
}
}
}
此时再运行vm.fullname = ‘jack mark’;时,就会调用计算属性的setter
二、监听器watch
虽然说计算属性在大多数情况下都用得非常舒服,但是有时,个别需求可能需要我们自定义一个监听器。
当需要在数据变动时执行异步操作或者开销较大时,这个方式是最有用的。
<div id = 'watch-example'>
<p>
<input v-model = 'question'>
</p>
<p> {{answer}} </p>
</div>
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<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 watchExample = new Vue({
el: 'watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
question : function(newQuestion) {
this.answer = 'Waiting for you to stop typing...';
this.getAnswer();
}
},
methods: {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
getAswer: _.debounce {
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
})
}
}
}
});
</script>
在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
除了 watch 选项之外,您还可以使用命令式的 vm.watchAPI.vm.watch API.
vm.watchAPI.vm.watch( expOrFn, callback, [options] )