狀態管理從0開始[後續更新]

Step01.命名一個storeService要一個只讀state
var storeService = new Object({
    _state: { age: 1 },
    get state() {
        return this._state;
    },
    set state(v) {
        throw new Error(' is read only.')
    }
});
Step02.建立一些列mutation改變state
var storeService = new Object({
    _state: { age: 1 },
    get state() {
        return this._state;
    },
    set state(v) {
        throw new Error(' is read only.')
    },
    mutationModifyAge(newAge) {
        state.age = newAge;
    },
    mutationModifyAge2(newAge) {
        state.age = newAge;
    },
    mutationModifyAge3(newAge) {
        state.age = newAge;
    }
});
Step03.須要一個watch監聽改變,每一次改變狀態的時候(執行mutation)調用listenCallback 返回狀態
var storeService = new Object({
    _listeners: [],
    _state: { age: 1 },
    get state() {
        return this._state;
    },
    set state(v) {
        throw new Error(' is read only.')
    },
    mutationModifyAge(newAge) {
        state.age = newAge;
        this._dealCallback();
    },
    mutationModifyAge2(newAge) {
        state.age = newAge;
        this._dealCallback();
    },
    mutationModifyAge3(newAge) {
        state.age = newAge;
        this._dealCallback();
    },
    _dealCallback() {
        this._listeners.forEach(listener => listener(this.state))

    },
    watch(listener) {
        // 優化想要第一次監聽的時候返回當前狀態
        listener(this.state);
        this._listeners.push(listener);
    }
});
// 監聽store
storeService.watch(function (state) {
    console.log('callback', state);
})
// 改變狀態
storeService.mutationModifyAge(2)
Step04.統一使用dispatch調用mutation法
var storeService = new Object({
    _listeners: [],
    _state: { age: 1 },
    get state() {
        return this._state;
    },
    set state(v) {
        throw new Error(' is read only.')
    },
    dispatch(type, ...paylod) {
        // 打印日誌信息
        console.log(type ? type : '監聽', '改變以前的狀態', this.state);
        if (this._mutation[type]) {
            this._mutation[type](this.state, ...paylod);
        }
        console.log(type ? type : '監聽', '改變以後的狀態', this.state);
        // 能夠少寫好多個listenCallback
        this._dealCallback();
    },
    _mutation: {
        mutationModifyAge(state, newAge) {
            state.age = newAge;
        },
        mutationModifyAge2(state, newAge) {
            state.age = newAge;
        },
        mutationModifyAge3(state, newAge) {
            state.age = newAge;
        }
    },
    _dealCallback() {
        this._listeners.forEach(listener => listener(this.state))

    },
    watch(listener) {
        // 優化想要第一次監聽的時候返回當前狀態
        // listener(this.state);
        // 優化讓第一次監聽也能夠記錄歷史日誌
        this.dispatch();
        this._listeners.push(listener);
    }
});
// 監聽store
storeService.watch(function (state) {
    console.log('callback', state);
})
// 改變狀態
storeService.dispatch('mutationModifyAge', 2)
以上內容爲建立一個簡單的store。
如下開始按照Vuex0.3.0開始優化
Step05.vuex dispatcher調用的方法是mutation,
mutation是惟一操做state的方法,
mutation不可包含任何反作用,
mutation對外暴露dispatch調用將上面的mutation 改成mutation
var storeService = new Object({
    _listeners: [],
    _state: { age: 1 },
    get state() {
        return this._state;
    },
    set state(v) {
        throw new Error(' is read only.')
    },
    dispatch(type, ...paylod) {
        // 打印日誌信息
        console.log(type ? type : '監聽', '改變以前的狀態', this.state);
        if (this._mutation[type]) {
            this._mutation[type](this.state, ...paylod);
        }
        console.log(type ? type : '監聽', '改變以後的狀態', this.state);
        // 能夠少寫好多個listenCallback
        this._dealCallback();
    },
    _mutation: {
        mutationModifyAge(state, newAge) {
            state.age = newAge;
        },
        mutationModifyAge2(state, newAge) {
            state.age = newAge;
        },
        mutationModifyAge3(state, newAge) {
            state.age = newAge;
        }
    },
    _dealCallback() {
        this._listeners.forEach(listener => listener(this.state))

    },
    watch(listener) {
        // 優化想要第一次監聽的時候返回當前狀態
        // listener(this.state);
        // 優化讓第一次監聽也能夠記錄歷史日誌
        this.dispatch();
        this._listeners.push(listener);
    }
});
// 監聽store
storeService.watch(function (state) {
    console.log('callback', state);
})
// 改變狀態
storeService.dispatch('mutationModifyAge', 2)
Step05.vuex中mutation爲純函數,不可包含任何反作用,添加action來處理一系列反作用,最終仍是調用dispatch 去改變state
var storeService = new Object({
    _listeners: [],
    _state: { age: 1 },
    get state() {
        return this._state;
    },
    set state(v) {
        throw new Error(' is read only.')
    },

    dispatch(type, ...paylod) {
        // 打印日誌信息
        console.log(type ? type : '監聽', '改變以前的狀態', this.state);
        if (this._mutation[type]) {
            this._mutation[type](this.state, ...paylod);
        }
        console.log(type ? type : '監聽', '改變以後的狀態', this.state);
        // 能夠少寫好多個listenCallback
        this._dealCallback();
    },
    _mutation: {
        mutationModifyAge(state, newAge) {
            state.age = newAge;
        },
        mutationModifyAge2(state, newAge) {
            state.age = newAge;
        },
        mutationModifyAge3(state, newAge) {
            state.age = newAge;
        }
    },
    _dealCallback() {
        this._listeners.forEach(listener => listener(this.state))
    },
    watch(listener) {
        // 優化想要第一次監聽的時候返回當前狀態
        // listener(this.state);
        // 優化讓第一次監聽也能夠記錄歷史日誌
        this.dispatch();
        this._listeners.push(listener);
    },
    bindAction(actions) {
        this.actions = Object.create(null);
        this._actions = Object.create(null);

        function createAction(action, store) {
            if (typeof action === 'function') {
                return (...payload) => action(store, ...payload)
            }
        }
        Object.keys(actions).forEach(name => {
            console.log(actions[name]);
            this._actions[name] = createAction(actions[name], this)
            if (!this.actions[name]) {
                this.actions[name] = (...args) => this._actions[name](...args)
            }
        })
    }
});
var actions = {
    // 包含反作用的action
    asyncModifyAge(store, ...paylod) {
        setTimeout(() => {
            store.dispatch('mutationModifyAge', ...paylod)
        }, 2000);
    },
    // 屢次調用dispatch
    asyncMulModifyAge(store, ...paylod) {
        setTimeout(() => {
            store.dispatch('mutationModifyAge', ...paylod)
        }, 2000);
        store.dispatch('mutationModifyAge2', ...paylod)
    }
}
storeService.bindAction(actions);
// 監聽store
storeService.watch(function (state) {
    console.log('callback', state);
})
// 改變狀態
storeService.dispatch('mutationModifyAge', 2)
storeService.actions.asyncMulModifyAge(21);
Step06 封裝成一個類hKeeper
var defaultOption = {
    state: {},
    actions: {},
    mutations: {}
};
class hKeeper {
    constructor(options) {
        options = Object.assign({}, defaultOption, options);
        this._state =  options.state;
        this.listeners = [];
        const dispatch = this.dispatch;
        this.dispatch = (...args) => {
            dispatch.apply(this, args);
        };
        this.actions = Object.create(null);
        this._setupMutations(options.mutations);
        this._setupActions(options.actions);
    }
    get state() {
        return this._state
    }

    set state(v) {
        throw new Error('[hKeeper] hKeeper state is read only.')
    }
    dispatch(type, ...payload) {
        const mutation = this._mutations[type]
        const state = this.state
        if (mutation) {
            mutation(state, ...payload)
        }
        this.listeners.forEach(listener => listener(this.state))
    }
    _setupMutations(mutations) {
        this._mutations = mutations;
    }
    // 設置action
    _setupActions(actions) {
        function createAction(action, store) {
            if (typeof action === 'function') {
                return (...payload) => action(store, ...payload)
            }
        }
        this._actions = Object.create(null)
        Object.keys(actions).forEach(name => {
            this._actions[name] = createAction(actions[name], this)
            if (!this.actions[name]) {
                this.actions[name] = (...args) => this._actions[name](...args)
            }
        })
    }
    watch(listener) {
        listener(this.state);
        this.listeners.push(listener)
    }
}
var storeService = new hKeeper(
    {
        state: { age: 1 },
        actions: {
            // 包含反作用的action
            asyncModifyAge(store, ...paylod) {
                setTimeout(() => {
                    store.dispatch('mutationModifyAge', ...paylod)
                }, 2000);
            },
            // 屢次調用dispatch
            asyncMulModifyAge(store, ...paylod) {
                setTimeout(() => {
                    store.dispatch('mutationModifyAge', ...paylod)
                }, 2000);
                store.dispatch('mutationModifyAge2', ...paylod)
            }
        },
        mutations: {
            mutationModifyAge(state, newAge) {
                state.age = newAge;
            },
            mutationModifyAge2(state, newAge) {
                state.age = newAge;
            },
            mutationModifyAge3(state, newAge) {
                state.age = newAge;
            }
        }
    }
)
// 監聽store
storeService.watch(function (state) {
    console.log('callback', state);
})
// 改變狀態
storeService.dispatch('mutationModifyAge', 2)
storeService.actions.asyncMulModifyAge(21);
參考Vuex0.3.0版本 applyMiddleware 參考Redux
https://github.com/HereSincer...
相關文章
相關標籤/搜索