computed计算属性
- 作用:用于在
data数据被渲染前的操作,有利于逻辑代码和模板的分离。这里指明是data中的数据,因为data中的数据是响应式的。 - 两种使用方式::
- 可以在计算属性中直接使用
this访问data的数据; - 使用回调函数的形式接受一个
vm实例通过vm实例访问data的属性
- 可以在计算属性中直接使用
- 注意点:computed中定义的属性名不能和data中的属性名重名,不然警告已经被定义
The computed property "categories" is already defined in data.
1. 基本使用
<!-- 示例1:-->
<div id="app">
<!-- 这种比较繁琐 -->
{{ this.firstName + ' ' + this.lastName }}
<!-- 计算属性的方式比较简洁 -->
{{ fullName }}
</div>
<script>
new Vue({
el: '#app',
data: {
firstName: 'Nice',
lastName: 'alice'
},
computed: {
// 通过箭头函数接受vm实例的方式
fullName: vm => vm.firstName.concat('-').concat(vm.lastName)
}
})
</script>
<!-- 示例2: -->
<body>
<!-- 308 --308 -->
<div id="app">{{ totalPrice }} -- {{totalPriceTwo}}</div>
<script>
var vm = new Vue({
el: "#app",
data: {
categories: [
{ id: 1, name: '计算机网络', price: 100 },
{ id: 2, name: '操作系统', price: 98 },
{ id: 3, name: '深入理解计算机系统', price: 110 },
]
},
// 通过this的方式
computed: {
totalPrice() {
return this.categories.reduce((a, b) => {
a.price += b.price
return a;
}, { price: 0 }).price
},
totalPriceTwo() {
return this.categories.map(item => item.price).reduce((a, b) => a + b);
},
},
});
</script>
</body>
2. 计算属性本质
- 计算属性的本质是包含
setter和getter方法的一个属性,所以在模板中访问的时候不是函数调用的方式,而是像访问data中的属性一样访问计算属性;说白了计算属性跟data中的数据属性一样是属性而不是方法。 - 如果没有自己实现set,那么计算属性默认是只读的,不能更改。
<!-- 示例1:本质写法 -->
<div id="app">{{ fullName }}</div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: 'Nice',
lastName: 'alice'
},
computed: {
// 本质是个包含setter和getter方法的对象; 在访问fullName属性时,会默认调用get函数,并将get函数的返回值作为fullName属性的值
fullName: {
set() { },
get() {
return this.firstName.concat(' ').concat(this.lastName)
}
}
}
});
</script>
// 示例2:简写过度阶段
computed: {
fullName: {
get() {
return this.firstName.concat(' ').concat(this.lastName)
}
}
}
// 示例3: 简写最终版————因为一般我们不希望别人给我们的计算属性设置值,所以就把set函数删掉了,相当于计算属性是个只读属性;那么计算属性都只有一个get方法,每次都写get方法太麻烦了,所以直接把get省略了
computed: {
fullName: function{
return this.firstName.concat(' ').concat(this.lastName)
}
}
<!-- 示例4:自己实现set函数
// 可以自己实现set方法,实现了set方法就不是只读属性了;
// 备注:自己实现的set方法,set方法是有一个参数的,fullName被赋值时的值就是set的参数
-->
<div id="app">{{ fullName }}</div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: 'Nice',
lastName: 'alice',
},
computed: {
fullName: {
// 当执行 vm.fullName = 'hello bob'时,就会默认调用set函数,newValue就等于'hello bob'
set(newValue) {
var names = newValue.split(' ')
this.firstName = names[0];
this.lastName = names[1];
},
get() {
return this.firstName.concat(' ').concat(this.lastName)
}
}
}
});
</script>
3. 计算属性缓存问题
- 计算属性的值
fullName会被缓存,它只会监听get中使用的data数据项里面的属性(比如data的flag没有被计算属性使用,所以flag的变化不会导致重新计算),如果有变化,则会重新更新计算属性 - 由于计算属性的值会被缓存,所以多次访问计算属性值只会调用一次get函数;所以计算属性比methods性能更好一点
<body>
<div id="app">
<h1>{{this.firstName + ' ' + this.lastName}}</h1>
<div>
methods方法调用次数:3次
<h1>{{getFullName()}}</h1>
<h1>{{getFullName()}}</h1>
<h1>{{getFullName()}}</h1>
</div>
<div>
computed属性调用次数:1次
<h1>{{fullName}}</h1>
<h1>{{fullName}}</h1>
<h1>{{fullName}}</h1>
</div>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: 'Nice',
lastName: 'alice',
flag: '111',
},
computed: {
fullName: vm => {
console.log('fullName');
return vm.firstName.concat(' ').concat(vm.lastName)
}
},
methods: {
getFullName() {
console.log('getFullName');
return this.firstName.concat(' ').concat(this.lastName)
}
}
});
</script>
</body>
- computed和methods的区别:
- computed计算属性值可以缓存,性能更好。(如果方法中有循环,那么使用方法则会每调用一次方法都会进行for循环)
- computed计算属性本质是一个属性,不是方法;methods定义的时方法
- computed除了可以使用基本函数的this访问data之外,还提供箭头函数接受参数vm实例的方式访问data数据;methods中的方法不能使用箭头函数的形式
- 场景选择:将data的数据做一些变化重新展示的情况建议选择
computed, 方法和computed都适用的情况下优先选择com
4. 场景
场景1:计算属性没有监听data中的数据,而是直接返回了123,这种情况不会报错,但是当我们在控制台修改vm.lastName值时,也就是改变dta中的值,计算属性fullname也感知不到,所以这种写法没有任何意义。
// 场景1:
<div id="app">
{{ fullName }}
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
firstName: 'Nice',
lastName: 'alice'
},
computed: {
fullName() {
return 123
}
}
})
</script>
场景2:在控制台修改temp变量的值为'hello',此时页面渲染fullName的值不会变化,还是初始的'xxx';但如果fullName中监听的是data中的属性值,那么在控制台中通过vm修改data中的值,此时页面会重新渲染fullName,因为data中的值是响应式的。
// 场景2:
<div id="app">
<!-- 在控制台修改temp的值,不会触发这里的重新渲染;这里一直保持temp的初始值xxx;因为temp不是响应式属性 -->
{{ fullName }}
</div>
<script>
var temp = 'xxx'
var vm = new Vue({
el: '#app',
data: {
firstName: 'Nice',
lastName: 'alice'
},
computed: {
fullName() {
return temp;
}
}
})
</script>
本文使用 mdnice 排版