文章首发: https://shudong.wang/10386.html
源码:https://github.com/wsdo/vuex-...
实现getter
当我们想实现getter的时候,先了解他的作用
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
实现思路
说白了,getter 就是把 state 经过一些逻辑过虑一下返回一个新的 state
这个逻辑 无非就是一个功能函数,so,我们应该实现一个函数,根据 state变化而变化
这时候,响应式数据的功劳 Object.defineProperty
首先我们来什么一个函数
接收参数
状态:因为我们要基于一个状态来处理返回一个状态所以需要一个状态
getter名字:我们在一个状态管理里面会有多个getter,所以会有getter名字,来区分
函数:因为我们要使用一个函数来处理一个逻辑,所以需要接收一个函数
函数如下
registerGetter(status,name,fn)
我们需要监听state状态,然后做出响应
const registerGetter = (store, fn, name) => {
Object.defineProperty(store.getters, name, {
get: () => {
return fn(store.state)
},
})
}
初始化的时候,需要让我们所有的,getter函数执行
const forEachValue = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key))
下面是实现getter的全部代码 可以慢慢试着去理解分析
参考仓库:
main.js
import Vue from 'vue'
import App from './App.vue'
import stark from './store'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
stark,
}).$mount('#app')
Stark.vue
created() {
console.log('getters',this.$stark.getters);
},
打印结果
store/index.js
import Vue from 'vue'
import Vuex from '../store'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 10,
},
getters: {
getNumOne(state) {
return state.count + 5
},
},
})
store.js
import applyMixin from './mixin'
import Vue from 'vue'
const forEachValue = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key))
const registerGetter = (store, fn, name) => {
Object.defineProperty(store.getters, name, {
get: () => {
return fn(store.state)
},
})
}
const resetStoreVM = (store, state) => {
store._vm = new Vue({
data: {
state: state,
},
})
}
export class Store {
constructor(options = {}) {
this.options = options
this.getters = {}
forEachValue(options.getters, (fn, name) => {
registerGetter(this, fn, name)
})
resetStoreVM(this, options.state)
}
get state() {
return this.options.state
}
}
export const install = Vue => {
applyMixin(Vue)
}
mixin.js
export default function(Vue) {
Vue.mixin({ beforeCreate: starkInit })
function starkInit() {
const options = this.$options
if (options.stark) {
this.$stark = typeof options.stark === 'function' ? options.stark() : options.stark
} else if (options.parent && options.parent.$stark) {
this.$stark = options.parent.$stark
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。