我们项目中最近使用了异步计算属性,个人感觉很好用,特此推荐给大家。
假设这样一个场景:
一个列表数据 data 是通过接口返回,请求参数中有一个 id 的数据,这个 id 数据变化的话,需要重新请求接口获取数据。
按照普通方法来的话,需要按以下步骤实现。
使用异步计算属性的话,只需要以下代码:
asyncComputed: {
list () {
return Vue.http.get('/get-list-by-id/' + this.id)
.then(response => response.data)
}
}
接下来,详细介绍一下异步计算属性。
npm install --save vue-async-computed
当使用了 webpack 或者 browserify 等时,需要明确通过 Vue.use 实现安装。
import Vue from 'vue'
import AsyncComputed from 'vue-async-computed'
Vue.use(AsyncComputed)
和同步计算属性类似,异步计算属性有 get 方法,但是没有 set 方法,设置了也会被忽略。
asyncComputed: {
blogPostContent: {
get () {
return Vue.http.get('/post/' + this.postId)
.then(response => response.data.postContent)
}
}
}
异步计算属性还可以设置默认值。在首次加载数据之前使用。
asyncComputed: {
blogPostContent: {
get () {
return Vue.http.get('/post/' + this.postId)
.then(response => response.data.postContent)
},
default: 'Loading...'
// default 也可以使用函数,设置基于其他数据的默认值
default () {
return 'Loading post ' + this.postId
}
}
}
默认值还可以全局设置。
Vue.use(AsyncComputed, {
default: 'Global default value'
})
有时候,异步计算属性的依赖项没有变化,但是需要重新计算。
当某个数据变化时的重新计算可以这么写。
new Vue({
data: {
postId: 1,
timesPostHasBeenUpdated: 0
},
asyncComputed: {
blogPostContent: {
get () {
return Vue.http.get('/post/' + this.postId)
.then(response => response.data.postContent)
},
// timesPostHasBeenUpdated 变化时重新计算
watch: ['timesPostHasBeenUpdated']
}
}
}
还可以通过点语法监听具体属性值。
watch: [‘a.b.c’, ‘d.e’] 可以监听 this.a.b.c 和 this.d.e.
另外还可以在某些情况下手动触发重新计算。
asyncComputed: {
blogPosts: {
get () {
return Vue.http.get('/posts')
.then(response => response.data)
},
}
},
methods: {
refresh() {
// 手动触发
this.$asyncComputed.blogPosts.update();
}
}
使用 watch 会重新计算,但是不会考虑监听属性的值得具体情况。
这个时候可以使用 shouldUpdate 实现具体条件下的重新计算。
asyncComputed: {
blogPostContent: {
get () {
return Vue.http.get('/post/' + this.postId)
.then(response => response.data.postContent)
},
// pageType 或者 postId 改变都会重新计算,但必须同时满足下面条件
shouldUpdate () {
return this.pageType !== 'index'
}
}
}
有时候不希望异步计算属性一直重新计算,可以使用 lazy:true 实现只在首次访问时计算。
asyncComputed: {
mightNotBeNeeded: {
// mightNotBeNeeded 的值只会在首次计算
lazy: true,
get () {
return Vue.http.get('/might-not-be-needed/' + this.id)
.then(response => response.data.value)
}
}
}
每个异步计算属性,都会向 $asyncComputed 中添加一个对象(包含有关该对象当前计算状态的信息)。
该对象包含以下属性:
{
// 之一:updating, success, error
state: 'updating',
// 布尔值,属性更新时为true
updating: true,
// 没有错误发生且当前值可用时,该属性不再更新
success: false,
// promise 出现 rejected
error: false,
// promise 出现 rejected 时的原始错误信息
exception: null
}
用于展示更新/错误信息。
asyncComputed: {
posts() {
return Vue.http.get('/posts')
.then(response => response.data)
}
}
}
// 每次 posts 数据更新时,以下信息都会展示
// (Re)loading posts
默认情况下,在异步计算属性中发生 promise 的 reject 的情况下,vue-async-computed 将为你记录错误。
如果你想使用自定义日志记录函数,那么插件将接受 errorHandler 选项,该选项应该是你希望使用错误信息调用的函数。
默认情况下,它将仅以错误的堆栈跟踪作为参数进行调用,但是如果将 errorHandler 与 useRawError 设置为 true,函数将接收原始错误,即抛出错误的Vue实例的引用和错误的堆栈跟踪。
Vue.use(AsyncComputed, {
errorHandler (stack) {
console.log('Hey, an error!')
console.log('---')
console.log(stack)
}
)
// useRawError
Vue.use(AsyncComputed, {
useRawError: true,
errorHandler (err, vm, stack) {
console.log('An error occurred!')
console.log('The error message was: ' + err.msg)
console.log('And the stack trace was:')
console.log(stack)
}
)
git 地址:vue-async-computed