一、computed选项
1、计算属性
语法:在computed选项中,定义计算属性方法,在方法体使用声明式变量进行若干计算。
2、计算属性一定是个函数。一定有返回值。
3、计算属性的作用
(1)用于优化指令的表达式,当指令的表达式比较复杂,我们建议使用计算属性来优化,提升视图模板中代码的可阅读性、可维护性。
(2)用于缓存一个复杂的计算,避免组件更新时产生没有必要的损耗。
(3)计算属性本质上是一个函数,vue会分析函数体中使用到了哪些声明式变量,有且仅有这些声明式变量发生变化时,计算属性才会重新执行。
二、例子
<html>
<head>
<title>计算属性</title>
<style>
[v-cloak] {display: none;}
</style>
</head>
<body>
<div id="app">
<h1 v-text='("总价:" + "¥" + (num*price).toFixed(2))'></h1>
<h1 v-text='total'></h1>
<hr>
<h1 v-text='Math.random() * count'></h1>
<h1 v-text='random'></h1>
<hr>
<button @click="test">用代码访问计算属性</button>
<hr>
<h1 v-text='total2'></h1>
<hr>
Firstname:<input type="text" v-model='firstname' />
Lastname:<input type="text" v-model='lastname' />
<h1 v-cloak>全名:<input type="text" v-model='fullname' /></h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
num: 1,
price: 10,
count: 100,
firstname: '张',
lastname: '兰兰'
},
methods: {
test() {
console.log('---total', this.total)
this.total = 100
}
},
computed: {
//计算属性一定要有返回值
total() {
//做一切可以做的复杂计算
const res = (this.num * this.price)
const tt = res.toFixed(2)
return '总价:¥' + tt
},
random() {
return Math.random() * this.count
},
total2: { //用对象的写法
get() {
return (this.num * this.price).toFixed(2)
},
set(newVal) {
this.price = newVal
return (this.num * this.price).toFixed(2)
}
},
fullname: {
get() {
return this.lastname + "*" + this.firstname
},
set(val) {
if (val.indexOf('*') === -1) {
throw new Error('字符串必须用*号分割')
}
const arr = val.split('*')
this.lastname = arr[0]
this.firstname = arr[1]
}
}
}
})
</script>
</body>
</html>
1、计算属性可以将复杂的表达式封装起来
要求把金额前加上人民币符号,金额带2位小数
直接写,就是一个很复杂的表达式:
<h1 v-text='("总价:" + "¥" + (num*price).toFixed(2))'></h1>
调用计算属性方法(当做变量来使用),就很方便:
<h1 v-text='total'></h1>
computed: {
//计算属性一定要有返回值
total() {
//做一切可以做的复杂计算
const res = (this.num * this.price)
const tt = res.toFixed(2)
return '总价:¥' + tt
}
}
2、计算属性可以避免更改一个变量时,另一个值也变了
组件更新时,页面复杂的计算也重新计算了
我更新app.price = 2,此时页面上:<h1 v-text='Math.random() * count'></h1>也会更新
用计算属性:<h1 v-text='random'></h1>就不会变化
3、控制台可以直接访问计算属性
app.total
app.random
4、计算属性默认只支持get操作
如果尝试在点击事件里设置计算属性的值
test() {
console.log('---total', this.total)
this.total = 100
}
报错信息:
[Vue warn]: Computed property "total" was assigned to but it has no setter.
(found in <Root>)
报错计算属性被修改,但是它没有setter
5、在视图模板中把计算属性直接当作变量直接使用,在vue逻辑代码使用this访问计算属性,默认只有get功能
6、如何让计算属性同时支持get/set功能呢
计算属性默认是一个函数,表示get功能。为了支持set,要把计算属性写成对象结构。
total2: { //用对象的写法
get() {
return (this.num * this.price).toFixed(2)
},
set(newVal) {
this.price = newVal
return (this.num * this.price).toFixed(2)
}
}
原先页面显示:
<h1 v-text='total2'></h1>
修改app.total2 = 3,页面自动变为了
7、问题:计算属性能不能绑定在v-model上
可以,计算属性要有set功能,拆成get/set写法。因为v-model是双向绑定,可以获取也可以设置。
Firstname:<input type="text" v-model='firstname' />
Lastname:<input type="text" v-model='lastname' />
<h1 v-cloak>全名:<input type="text" v-model='fullname' /></h1>
fullname: {
get() {
return this.lastname + "*" + this.firstname
},
set(val) {
if (val.indexOf('*') === -1) {
throw new Error('字符串必须用*号分割')
}
const arr = val.split('*')
this.lastname = arr[0]
this.firstname = arr[1]
}
}
8、问题:计算属性能计算哪些性质的变量呢
除了可以计算data、vuex数据、$route路由数据等,还可以计算一切带有__ob__的数据。
经常拿计算属性来计算状态管理vuex中的数据,route路由url数据。