Vue 异步计算属性实现

前段时间在 GitHub 上看到一个 Vue 异步计算属性的库 - vue-async-computed, 将异步操作转化为计算属性, 例如这样用

1
2
3
4
5
6
7
8
9
10
11
new Vue({
data: {
userId: 1
},
asyncComputed: {
username () {
return Vue.http.get('/get-username-by-id/' + this.userId)
.then(response => response.data.username)
}
}
}

好奇其中原理, 看了源码, 了解其中巧妙的实现思路, 绘制了一张核心思路的原型图.

接下来我们实现一个简(阉)易(割)版本的 vue-async-computed 插件,

趁着 beforeCreatedata 中添加 asyncComputedkey, 使之响应式.

1
2
3
4
5
6
7
8
9
10
11
12
13
Vue.mixin({
beforeCreate() {
const data = this.$options.data;
this.$options.data = function() {
let _data = typeof data === "function" ? data.call(this) : data; // 有的时候 data 可能不是函数, 而是对象

// 遍历 asyncComputed 注册 key
for (const key in this.$options.asyncComputed || {}) {
_data[key] = null;
}
return _data ? _data : {};
};
});

注入计算魔改后的计算属性

1
2
3
4
5
6
7
8
9
10
11
const prefix = "async$";
Vue.mixin({
beforeCreate() {
for (const key in this.$options.asyncComputed || {}) {
if (!this.$options.computed) {
this.$options.computed = {};
}
this.$options.computed[prefix + key] = this.$options.asyncComputed[key];
}
}
});

createdwatch 魔改后的计算属性, 并且更新 data 上的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Vue.mixin({
created() {
for (const key in this.$options.asyncComputed || {}) {
this.$watch(
prefix + key,
newPromise => {
newPromise()
.then(val => {
this[key] = val;
})
.catch(err => {
console.log(err);
});
},
{ immediate: true } // watch 之后立即调用一次, 因为此时有 Promise 实例了
);
}
}
});

以上只是简单的实现, 源码其实还包括 lazy 计算属性, 默认值, 错误处理等特性, 具体可以看源码. 这是注释版源码
vue-async-computed

# Vue

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×