在上篇文章中,我们已经实现了对所有的Vue
实例绑定同一个store
实例。
回顾Vuex
的使用
Vue
官网vuex的使用
实现一个Store
类
- 通过上面官网的介绍,我们可以知道数据的访问,都是通过
store.
的方式来进行的,也就是说,store
的实例上必须有这些属性,根据这个,我们来设计一个Store
类。 store.
的属性都来自传递进来的参数对象
class Store{
constructor(options){
this.data = options.state;
let getters = options.getters || {}
this.getters = {}
// 把getter对象上的属性全部绑定到this.getter上
Object.keys(getters).forEach((key) => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](this.state)
})
})
}
get state(){
return this.data
}
}
也许这段代码,你有些地方看不懂,为什么要这么做,不慌,到后面,都会一一讲清楚,讲明白...
在上面的代码中,我们将传进来的getter
中的所有属性全部复制了一份绑定到了this.getter
上。
存在这样一个疑问就是我们为啥不直接让this.getter直接指向options.getter干嘛还要多此一举
像下面这样写不是更加简洁吗?而且还更节省空间。
class Store{
constructor(options){
this.state = options.state;
this.getters = options.getters;
}
}
var store = new Store({
state:{
name:'iamsmiling'
},
getters:{
getName:(state)=>state.name
}
})
哇,看上去好好有道理啊!
不过,存在这样一个问题,我们store.getters.getName
时,我们得到的时是一个函数对象,也就是(state)=>state.name
.
也许你会说,这简单啊,我们直接再加个括号不就完事了吗?但真的是这样吗?
store.getters.getName()
,报错了因为getName()
没有传递参数。
那我们再加个参数进去呗,于是变成了这个样子store.getters.getName(store.state)
最后,我们终于如愿得到了我们想要的iamsmilling
但我们再回头看一下,在vuex
中,我们是如何调用的
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
对比一下,我们实现的store.getters.getName(store.state)
和 store.getters.doneTodos
,我们的版本显然很鸡肋。
有什么办法可以改善呢?我们模仿Vuex
源码的方式,对我们的代码进行修正和完善:
class Store{
constructor(options){
this.data = options.state;
let getters = options.getters || {}
this.getters = {}
// 把getter对象上的属性全部绑定到this.getter上
Object.keys(getters).forEach((key) => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](this.state)
})
})
}
get state(){
return this.data
}
}
var store = new Store({
state: {
name: 'iamsmiling'
},
getters: {
getName: (state) => state.name
}
})
console.log(store.getters.getName) // 输出iamsmiling
现在,我们也可以通过store.getters.getName
来进行访问了,姿势也变得优雅了。