计算属性
计算属性可以同时设置getter()、setter()方法,是以函数形式,在vue实例的选项对象的comoputed选项中定义的。
前面做了一个字符串翻转的案例
<div id="app">
<input v-model="message">
<p>{{message.split('').reverse().join("")}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "Hello Vue.js!"
},
methods: {
reverseMessage(){
}
}
})
</>
通过使用computed计算属性的语法:
<div id="app">
<input v-model="message">
<p>{{reverseMessage}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
// 属性
data: {
message: "Hello Vue.js!"
},
// 方法
methods: {
reverseMessage(){
}
},
// 计算属性
computed: {
// 声明了一个计算属性reverseMessage,给出的函数将用作属性vm.reverseMessage的getter函数。
reverseMessage: function(){
return this.message.split('').reverse().join("");
}
}
})
</script>
当msg属性的值改变时,reverseMessage的值也会自动更新,并且会自动同步更新DOM部分。在浏览器中的控制窗口修改vm.msg的值,可以发现reverseMessage的值也会随之发生变化.
计算属性默认只有getter,因此是不能直接修改计算属性的,如果需要可以提供一个setter,如下例:
<div id="app">
<input v-model="message">
<p>{{reverseMessage}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "Hello Vue.js!"
},
methods: {
},
// 计算属性
computed: {
reverseMessage: {
set(newValue){
this.message = newValue;
},
// 计算属性一般是没有set方法,只读属性
get(){
return this.message.split('').reverse().join("");
}
}
}
})
</script>
在浏览器控制台中修改vm.reverseMessage=’123456’后的效果图如下,可以看到值都同时变化了,这是调用reverseMessage的setter函数来实现的。
侦听器属性
机制:watch内的函数名 === data中的属性名
触发:data中的属性名对应的值发生改变时,就会触发watch内的函数就执行
参数:watch中的函数有两个参数,一个是new新值,一个old旧值。
<input v-model="firstName" />
<input v-model="lastName" />
<div id="demo">{{ fullName }}</div>
<script>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
this.fullName = this.firstName + ' ' + val
}
}
})
</script>
计算属性和侦听属性的区别
watch:监测的是属性值, 只要属性值发生变化,其都会触发执行回调函数来执行一系列操作;
computed:监测的是依赖值,依赖值不变的情况下其会直接读取缓存进行复用,变化的情况下才会重新计算;
区别是:计算属性不能执行异步任务,计算属性必须同步执行。也就是说计算属性不能向服务器请求或者执行异步任务。如果遇到异步任务,就交给侦听属性。Watch也可以检测computed属性。
计算属性是基于它的响应式data中的数据依赖进行缓存的,只有在计算属性的相关响应式依赖发生改变时才会重新求值。而方法和监听器不存在缓存
利用插值表达式计算商品金额
<div id="app">
<p>数量:<input type="number" v-model="num" min="0"></p>
<p>单价:<input type="number" v-model="price"></p>
<p>总金额:{{num*price}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num: 0,
price: 0,
},
})
</script>
使用计算属性来实现商品金额的计算
<div id="app">
<p>数量:<input type="number" v-model="num" min="0"></p>
<p>单价:<input type="number" v-model="price"></p>
<p>总金额:{{amount}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num: 0,
price: 0,
},
methods: {
},
// 计算属性
computed: {
amount() {
return this.num * this.price;
}
},
})
</script>
分析:computed就是计算属性,从字面意思能计算也就是把单价乘上数量,最终生成了金额。
要注意计算属性是有缓存的,也就是只要当单价或者数量发生变化,和缓存中的值不同的时候,才会重新计算。
如果单价或者数量没有发生变化,computed不会重新计算。
使用侦听器属性来实现商品金额的计算
<div id="app">
<p>数量:<input type="number" v-model="num" min="0"></p>
<p>单价:<input type="number" v-model="price"></p>
<p>总金额:{{total}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
num: 0,
price: 0,
total: null,
},
methods: {
},
// 计算属性
computed: {
amount() {
return this.total = this.num * this.price;
}
},
// 监听器属性
watch: {
num(newNum, oldNum) {
console.log(newNum, oldNum);
this.total = newNum * this.price;
},
price(newP, oldP) {
console.log(newP, oldP);
this.total = this.num * newP;
}
}
})
</script>
注意:监听器实现,从字面意思上也是能理解,监听既是监听单价和数量的变化,如果有变化,那么total就会被重新赋值。这里呢,有一个total默认值的。
三种方法相比,计算属性最佳,代码相比监听器属性也比较少。虽然第一种最简单,但是不推荐在插值表达式中书写逻辑计算代码。