一、Vue的计算属性
1.1 什么是计算属性?
在说明计算属性时,不得不提一下插值表达式。
<body>
<div id="root">
<h1>Hello {{name}}</h1>
</div>
<script>
const vm = new Vue({
el:'#root',
data(){
return{
name:'小柴'
}
}
})
</script>
</body>
上面这个实例应该是我们学Vue时第一次接触的插值表达式实例。从这个实例不难看出,插值表达式的语法非常简单,它也是一个能很好体现Vue中MVVM模型中数据绑定非常好的实例。但是也不免暴露出它的一些缺点:
不好进行复杂逻辑运算,(这里指的是会使得模板变的复杂,不容易理解) 而且编译器还没提示,因为是写在双括号里😢。
比如菜鸟教程中提供了一个字符串反转的例子,小编这里把姓名进行反转(利用插值表达式的方式)
<body>
<div id="root">
<h1>Hello {{name.split('').reverse().join('')}}</h1>
</div>
<script>
const vm = new Vue({
el:'#root',
data(){
return{
name:'小柴'
}
}
})
</script>
</body>
那肯定很多人疑惑,上面的问题用方法(methods
)不就可以进行解决了:
<body>
<div id="root">
<h1>Hello {{rev()}}</h1>
<h1>Hello {{rev()}}</h1>
<h1>Hello {{rev()}}</h1>
</div>
<script>
const vm = new Vue({
el:'#root',
data(){
return{
name:'小柴'
}
},
methods:{
rev(){
return this.name.split('').reverse().join('')
}
}
})
</script>
</body>
等小编说完计算属性,就知道和 methods 有什么区别了(首先这里可以观察到三次执行都rev方法),就知道这种操作为什么不用methods了。
-
计算属性的本质是辅助插值表达式来进行逻辑运算的,它在处理一些复杂逻辑是很有用的。
-
计算属性关键字:
computed
,翻译:计算 -
计算属性就是把
data
中已有的属性进行加工后得出来一个新的‘属性’(计算出来的结果在调用时会存到vue中,以属性的方式)。
下面使用计算属性的方式实现上面的实例(computed和methods不同,computed内部放的是对象,里面可以写getter和setter方法,getter调用后其对象名会成为vm对象中的属性名,其getter方法的返回值会成为这个对象名对应的属性值(有简写方式,直接是函数然后返回值替代那个getter,但那样setter就使用不了了,而且对初学者来说不好理解,本篇博客没有提供简写方式))
<body>
<div id="root">
<h1>Hello {{ans}}</h1>
</div>
<script>
const vm = new Vue({
el:'#root',
data(){
return{
firstName:'小',
secondName:'柴'
}
},
computed:{
ans:{
get(){
const fullName = this.firstName + this.secondName
return fullName.split('').reverse().join('')
}
}
}
})
</script>
</body>
这里的get方法只被调用了一次。
从这案例可以看出与methods
实现相比,computed
的优势:
- computed内部有缓冲机制,提高了复用,get执行后,其结果就会存入vm对象中,那么在模块中调用了直接取即可,效率高。
1.2 getter和setter细节和computed案例
setter方法调用时机和作用:
上面说了调用getter方法后属性会存入到 vm 对象中,也就是说当vm对象中的这个属性发生改变了,那么就会去调用对应的setter方法。setter方法被调用,肯定是去拿改变后的值去反过来修改其getter所依赖的属性,从而使得再次去调用getter方法,让缓存更新。
下面说说getter何时被调用:
- 初次被读取时;
- 所依赖的属性发生更改时。(上面讲述了,computed 一般是去使用data中已有的属性去得到没有的‘属性值’,那么当所使用的属性发生改变的时候,会去调用getter方法,而不是找缓存,调了getter,那对应的缓存也应该发生改变。)
小编在计算属性这篇博客中看见一个案例,觉得挺好,这里再写一下(他的vue博客写的很不错,个人推荐)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../lib/vue2.js"></script>
</head>
<body>
<div id="root">
全选<input type="checkbox" v-model="allCheck"/>
<ul>
<li v-for="(item,index) in list">
<input type="checkbox" v-model="item.select"/> <label for="">{{item.name}}</label>
<!--这个label标签是和input连用的,id要和input相同,然后其属性值就会对应input值-->
<!-- 但是它没这样用,他在input后面加的,不知道为什么 -->
<!-- 这里感觉用的好巧妙,土狗的震惊 -->
</li>
</ul>
</div>
<script>
const vm = new Vue({
el:'#root',
data(){
return {
// 属性值不想写,直接copy他的,哈哈哈
list:[
{ name: '前端', select: false },
{ name: 'UI', select: false },
{ name: 'Java', select: false },
{ name: 'php', select: false },
{ name: 'python', select: false },
{ name: 'c', select: false },
{ name: '测试', select: false },
{ name: '产品', select: false }
]
}
},
computed:{
allCheck:{
get(){
// 这里注意上面是全选对应的value值应该的布尔类型的,为true的话就有勾勾,反之就木的
// 那这里也应该返回布尔类型的
// 其条件就是对应的list属性中是否全是true
// every返回是布尔值,一假则假,全真为真
return this.list.every(item=>item.select)
},
set(val){
console.log(val)// 这个用来给自己一个提示,看看到底有没有全选
this.list.forEach(element =>
element.select = val
)
}
}
}
})
</script>
</body>
</html>
下面是那个博主对这个设计的思路:
二、总结
通过上面的概述不难发现,Vue 的 computed
主要是用来简化结构代码的,让开发人员更专注与数据层的操作,在所固定的属性中进行操作,使得在某种程度上属性变成了动态的(setter),在代码可复用的情况下,拥有缓存,提高代码的运行速度。