手写vuex
任务分析
实现一个插件:声明Store类,挂载$store
Store具体实现:
- 创建响应式的state,保存mutations、actions和getters
- 实现commit根据用户传入type执行对应mutation
- 实现dispatch根据用户传入type执行对应action,同时传递上下文
- 实现getters,按照getters定义对state做派生
定义vuex.js
store/vuex.js
let Vue;
class Store{
/**
* 下面构造参数options格式:
* {
state: {},
mutations: {},
actions: {},
getters: {}
}
*/
constructor(options){
/*
下面mutations格式
mutations: {
add(state){
state.count++
}
}*/
this._mutations = options.mutations
this._actions = options.actions
this._wrappedGetters = options.getters
// 响应化处理state
this.state = new Vue({
// 根组件直接赋值,不用函数
data: options.state
})
}
// type: add
// playload是参数
commit(type, payload){
// 拿到用户在index定义的mutations
const entry = this._mutations[type];
if(entry){
entry(this.state, payload)
}
}
dispatch(type, payload){
// 拿到用户在index定义的actions
const entry = this._actions[type];
if(entry){
// this就有dispatch/commit
entry(this, payload)
}
}
}
function install(_Vue){
Vue = _Vue
Vue.mixin({
beforeCreate(){
if(this.$options.store){
Vue.prototype.$store = this.$options.store
}
}
})
}
export default{
Store,
install
}store/index.js
import Vue from 'vue'
import Vuex from './vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 10
},
mutations: {
add(state){
state.count++
}
},
actions: {
add({ commit }){
setTimeout(() => {
commit('add')
}, 1000)
}
}
})
效果

但是点击dispatch时发现报错。原因是vuex.js的commit没有绑定this,如果commit在定时器提交,this就会乱
修改代码,下面代码放在vuex.js的store的构造里
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)再点击dispatch就会发现等待一秒count+1了
继续优化
将vuex.js的store的构造中的
// 响应化处理state
this.state = new Vue({
// 根组件直接赋值,不用函数
data: options.state
})换成
// 严格模式下官方定义了watch,只要有任何修改就报错
this._vm = new Vue({
data: {
// 加两个$,Vue不做代理,无法通过_vm拿到
$$state: options.state,
}
})再定义读取函数作为vuex.js的store的普通函数
// 存取器
// this.state返回this._vm._data.$$state
get state(){
// _data可换成$data
return this._vm._data.$$state
}
set state(v){
console.error('不允许直接修改哦')
}此时,直接this.$store.state.count = {}会报错

加入getters支持
也是完整demo代码
store/vuex.js
let Vue;
class Store{
/**
* options:
* {
state: {},
mutations: {},
actions: {},
getters: {}
}
*/
constructor(options){
/*
下面mutations格式
mutations: {
add(state){
state.count++
}
}*/
this._mutations = options.mutations
this._actions = options.actions
this._wrappedGetters = options.getters
// 定义computed选项
const computed = {}
this.getters = {}
// computed无参,这里有state需要进行封装
// doubleCounts(state){ return state.count *= 2 }
const store = this
Object.keys(this._wrappedGetters).forEach(key => {
// 获取用户定义的getter,注意fn带了state参数
const fn = store._wrappedGetters[key]
// 转换为computed可以使用的无参数形式
computed[key] = function(){
// 把this.state传递进去
return fn(store.state)
}
// 为getter定义只读属性
Object.defineProperty(store.getters, key, {
get: () => store._vm[key]
})
})
/* // 响应化处理state
this.state = new Vue({
// 根组件直接赋值,不用函数
data: options.state
})
*/
// 严格模式下官方定义了watch,只要有任何修改就报错
this._vm = new Vue({
data: {
// 加两个$,Vue不做代理,无法通过_vm拿到
$$state: options.state,
},
computed
})
// 绑定commit.dispatch的上下文store实例,没有绑定this,如果commit在定时器提交,this就会乱
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
// 存取器
get state(){
// _data可换成$data
return this._vm._data.$$state
}
set state(v){
console.error('不允许直接修改哦')
}
// type: add
// playload是参数
commit(type, payload){
// 拿到用户在index定义的mutations
const entry = this._mutations[type];
if(entry){
// this.state返回this._vm._data.$$state
entry(this.state, payload)
}
}
dispatch(type, payload){
// 拿到用户在index定义的actions
const entry = this._actions[type];
if(entry){
// this就有dispatch/commit
entry(this, payload)
}
}
}
function install(_Vue){
Vue = _Vue
Vue.mixin({
beforeCreate(){
if(this.$options.store){
Vue.prototype.$store = this.$options.store
}
}
})
}
export default{
Store,
install
}store/index.js
import Vue from 'vue'
import Vuex from './vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 10
},
mutations: {
add(state){
state.count++
}
},
actions: {
add({ commit }){
setTimeout(() => {
commit('add')
}, 1000)
}
},
getters: {
// 返回2倍的count
doubleCounts(state){
return state.count * 2
}
}
})效果

Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.
1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino
我一直梦想, 看到你们相册那样的地方。真棒。
我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。
我热爱这样的想法, 去那么多国家。真的很鼓舞。
能感受到热爱。继续保持 感受。
我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。
1
1
1