深入Vue的computed属性
Vue模板的表达式语法仅支持单个表达式,用于简单运算;对于复杂的逻辑计算应当使用计算属性computed。computed可以依赖(计算)props、data、vuex的数据,即可以声明了一个计算属性,令其响应props/data/vuex的数据变化,返回一个经过某种计算的结果。
Vue模板的表达式语法仅支持单个表达式,用于简单运算;对于复杂的逻辑计算应当使用计算属性computed。
computed可以依赖(计算)props、data、vuex的数据,即可以声明了一个计算属性,令其响应props/data/vuex的数据变化,返回一个经过某种计算的结果。
计算属性的写法
computed属性的属性值可以是函数或者对象
1、属性值是函数,这时候计算属性只有 getter
<div id="app">
{{fullName}}
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
2、属性值是对象
computed的属性值是对象时,对象的属性属性可以配置get和set方法,通过这种方式可以给计算属性提供一个 setter。
fullName: {
get () {
return this.firstName + ' ' + this.lastName
},
set (newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
计算属性支持缓存
在视图发生了变化,而计算属性所依赖的数据没有变化的情况下,会直接从缓存中取值。
下面的例子中计算属性messageLength和方法getMessageLength实现相同的功能,在通过点击按钮更新视图时,会发现方法getMessageLength会被执行,显然在这种情况下使用计算属性比方法性能更好。
<div id="app">
{{messageLength}}-{{getMessageLength()}}
<button @click="onClick">点击{{i}}</button>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
message: 'Hello world',
i: 0
},
computed: {
messageLength () {
console.log('messageLength执行了')
return this.message.length
}
},
methods: {
getMessageLength () {
console.log('getMessageLength执行了')
return this.message.length
},
onClick () {
this.i++
}
}
})
</script>
计算属性传参
在Vue实例中,计算属性以属性的方式存在,如果要传参,需要使用闭包将属性值改为一个函数
computed: {
fullName () {
return function (maxLength) {
return (this.firstName + ' ' + this.lastName).substring(0, maxLength)
}
}
}
这种情况下,使用计算属性与使用方法等效。
computed属性与watch属性
计算属性可以响应Vue 实例的数据变动,watch属性同样可以观察和响应 Vue 实例上的数据变动。
watch可以监听props、data和computed中的数据变化,并执行一个函数。
使用时:
computed是用来计算的,它要求返回一个结果,在调用的时候不需要加括号,它会根据一个或多个依赖
自动缓存,如果依赖不变,computed不会自动计算;
watch是用来监听的,一次只能监听一个数据
,监听的数据变化了,就去执行函数,它有两个选项:
- immediate表示在组件第一次渲染的时候是否要执行这个函数,默认为false。
- deep表示监听一个对象内部属性的变化,默认为false.
实现异步计算
一、computed属性无法返回异步操作的结果,但可以依赖Vuex中的数据,故通过返回store.state可以获得异步操作的结果
二、通过vue-async-computed插件可以实现异步计算属性,list属性将被赋值为一个Promise,显然不是我们需要的结果
import Vue from 'vue'
import AsyncComputed from 'vue-async-computed'
import axios from 'axios'
Vue.use(AsyncComputed)
export default {
name: 'MediaIndex',
data () {
return {
pageNo: 1
}
},
computed: {
list () {
return axios(`https://www.fastmock.site/mock/d6b39fde63cbe98a4f2fb92ff5b25a6d/api/products?pageNo=${this.pageNo}`)
.then(res => res.data)
}
},
asyncComputed: {
asyncList () {
return axios(`https://www.fastmock.site/mock/d6b39fde63cbe98a4f2fb92ff5b25a6d/api/products?pageNo=${this.pageNo}`)
.then(res => res.data)
}
}
}
巧用computed属性计算props
下面的例子实现props的双向绑定
export default {
name: 'Pagination',
props: {
page: {
type: Number,
default: 1
},
limit: {
type: Number,
default: 10
}
},
computed: {
currentPage: {
get() {
return this.page
},
set(val) {
this.$emit('update:page', val)
}
},
pageSize: {
get() {
return this.limit
},
set(val) {
this.$emit('update:limit', val)
}
}
}
更多推荐
所有评论(0)