计算属性
使用场景
如果一个结果需要依赖data中的数据,但是需要经过一些逻辑处理,才能得到你想要的数据。此时就可以使用计算属性。
例如:要对给定的字符串做翻转处理之后再来显示
<div id="app">
<!-- 此处逻辑复杂 -->
<h3>{{msg.split('').reverse().join('')}}</h3>
</div>
<script src="./vue.js"></script>
<script>
export default {
data(){
return {
msg: 'javascript'
}
}
}
</script>
\
定义格式
在vue实例中,补充computed配置项。
{
data(){},
methods: {}
// 声明计算属性
computed: {
//属性名字(计算属性名称)
//属性的值(计算属性处理函数)
计算属性名1 () {
// 对依赖的数据进行处理,且进行return
return
},
计算属性名2 () {
// 对依赖的数据进行处理,且进行return
return
}
}
}
} } })
computed 是vue的配置选项,它的值是一个对象,其中可定义多个计算属性,每个计算属性就是一个函数。
- 属性名称: 计算属性的名称
- 属性的值:计算属性的素材函数
-
- 对需要依赖的数据,进行逻辑上的处理
- 处理完毕后,需要return出去,返回的值就是计算属性的值
使用格式
在两个地方使用:
- 模板
-
- 用插值表达式 {{计算属性名}}
- 用其它指令
- 在实例内
-
- this.计算属性名
示例:颠倒字符串
<div id="app">
<!-- 逻辑复杂 -->
<h3>{{msg.split('').reverse().join('')}}</h3>
<!-- 计算属性 和data类似-->
<h3>{{reverseMsg}}</h3>
</div>
<script src="./vue.js"></script>
<script>
{
data () {
return { msg: 'hi vue' }
},
// 声明计算属性
computed: {
//属性名字(计算属性名称)
//属性的值(计算属性处理函数)
reverseMsg () {
// 对依赖的数据进行处理,且进行return
return this.msg.split('').reverse().join('')
}
}
})
</script>
- 在模板中使用计算属性,和使用data的方式是一样的。
-
- 虽然在计算属性中声明的是函数,但是在模板中使用,当中数据来使用,不需要加括号。
总结
- 什么时间用:需要对数据进行复杂的逻辑加工,产生新的数据时。
- 定义: 就是一个特殊的配置项computed。其中有多个函数。
- 使用:计算属性的使用方式与data中的数据项一致;
-
- 计算属性-计算:这个值是对原数据进行计算之后得到的新的数据
- 计算属性-属性:它的使用方法与原数据一样。this.计算属性名,{{计算属性名}}
- 执行的时机: 如果计算属性中依赖的数据项变化时,它会自动调用。
computed有缓存
问:
当我们在模板中来显示一份经过对数据项进行复杂计算之后的结果时,我们有两种解决方案:
- 计算属性
- 函数
应该如何选择?
答:
- methods定义函数,如果在模板中使用,每使用一次,就相当于调用了一次,处理逻辑会重新执行。
- computed定义计算属性,如果在模板中使用,使用多次,但是如果依赖的数据不发生改变,计算属性对应的函数不会重新执行。
-
- 计算属性会做缓存,提高渲染的性能。
示例
<div id="app">
<h3>学习计算属性</h3>
<p>计算属性:{{ reversedMsg }}</p>
<p>计算属性:{{ reversedMsg }}</p>
<p>计算属性:{{ reversedMsg }}</p>
<hr>
<p>函数:{{fReversedMsg()}}</p>
<p>函数:{{fReversedMsg()}}</p>
<p>函数:{{fReversedMsg()}}</p>
</div>
<script>
// 计算属性的特点:缓存
// - 如果计算属性所依赖的数据项并没有发生变化,则就算使用多个计算函数,其函数也只执行一次
// 因为它把结果缓存起来了。
{
data() {
return { msg: 'javascript' }
},
methods: {
updateMsg () {
this.msg = "abc"
// 由于计算属性有缓存,虽然在页面上用到三次,但它的函数体只执行一次。
// 对于普通的函数,在页面上用到了三次,它就会执行三次
},
fReversedMsg () {
console.log( '函数 fReversedMsg' )
//把msg的翻转一下
let newMsg = this.msg.split('').reverse().join('')
return newMsg
}
},
computed: {
reversedMsg () {
console.log( 'reversedMsg' )
//把msg的翻转一下
let newMsg = this.msg.split('').reverse().join('')
return newMsg
}
}
})
</script>
总结:
- 计算属性有缓存,提高渲染性能。
- 如果在页面上需要用到 对现有的数据进行加工得到新数据,则时要使用计算属性
案例-品牌管理(总价和均价)
目标
基于之前的案例, 完成总价和均价的计算效果
代码
<tr style="background-color: #EEE">
<td>统计:</td>
<td colspan="2">总价钱为: {{ allPrice }}</td>
<td colspan="2">平均价: {{ svgPrice }}</td>
</tr>
<tfoot v-if="list.length == 0">
<tr>
<td colspan="5" style="text-align: center">暂无数据</td>
</tr>
</tfoot>
<script>
export default {
// ...源代码省略
computed: {
allPrice(){
return Math.floor(this.list.reduce((sum, obj) => sum += obj.price, 0))
},
svgPrice(){
return Math.floor(this.allPrice / this.list.length)
}
}
}
</script>
总结: 总价来源于所有数据计算而来的结果, 故采用计算属性
计算属性-完整写法(难点-了解)
目标
计算属性也是变量, 如果想要直接赋值, 需要使用完整写法=>开启读写模式
语法
computed: {
"属性名": {
set(值){
},
get() {
return "值"
}
}
}
需求
- 计算属性给v-model使用
页面准备输入框
<template>
<div>
<div>
<span>名字:</span>
<input type="text" v-model="full">
</div>
</div>
</template>
<script>
export default {
data () {
return {
msg: 'full'
}
},
computed: {
full: {
get(){ // 获取full的值
console.log("get方法触发");
return this.msg
},
set(val){ // 要给full赋值
console.log(val)
this.msg = val
}
}
}
}
</script>
总结: 想要给计算属性赋值, 需要使用set方法