vuex基本使用
// store/index.js
import Vue from 'vue'
import Vuex from '../vuex'
Vue.use(Vuex)
export default new Vuex.Store({
plugins: [],
state: {
time: 1,
userInfo: {
avatar: '',
account_name: '',
name: ''
},
},
getters: {
getTime (state) {
console.log('1212',state)
return state.time
}
},
mutations: {
updateTime(state, payload){
state.time = payload
}
},
actions: {
operateGrou({ commit }) {
// commit('updateTime', 100)
return Promise.resolve().then(()=>{
return {
rows: [1,2,3]
}
})
}
}})
// main.js
import Vue from "vue";
import App from "./App.vue";
import store from "./store";
new Vue({
// 为了在 Vue 组件中访问 this.$store property,你需要为 Vue 实例提供创建好的 store。
// Vuex 提供了一个从根组件向所有子组件,以 store 选项的方式“注入”该 store 的机制
store,
render: h => h(App)
}).$mount("#app");
vuex实现原理
// vuex基本思想
let myVue
class Store{
// 这里options获取到的是用户new Store实例时传入所有属性
constructor(options){
// 1. state实现
// 核心点:这里将state借助vue设置成响应式。这也是vuex只能用于vue的一个原因
this.vm = new myVue({
data: {
return {
state: options.state
}
}
})
// 将this.state的获取写成函数的类属性访问器形式,便于扩展
// this.state = this.vm.state
// 2. getters实现
let getters = options.getters
this.getters = {}
// 因为getters传入的是个对象,对象中属性全部是函数,但是使用时确是当做属性使用,所以这里需要借助Object.defineProperty实现(就跟计算属性的实现方式一样)
Object.keys(getters).forEach(getterName => {
Object.defineProperty(this.getters, getterName, {
get: () => {
// getters[getterName] 获取到函数
return getters[getterName](this.state)
}
})
})
// 3. mutations实现(结合commit方法)(发布订阅模式)
let mutations = options.mutations
this.mutations = {}
Object.keys(mutations).forEach(mutationName => {
this.mutations[mutationName] = (payLoad) => {
mutations[mutationName](state, payLoad)
}
})
// 4. actions实现(发布订阅模式)
let actions = options.actions
this.actions = {}
Object.keys(actions).forEach(actionName => {
this.actions[actionName] = (payLoad) => {
actions[actionName](this, payLoad)
}
})
}
// 类属性访问器
get state(){
return this.vm.state
}
// 发布的时候回找对应mutationName的函数执行
commit = (mutationName, payLoad) => {
this.mutations[mutationName](payLoad)
},
// 发布的时候回找对应actionName的函数执行
dispatch = (actionName, payLoad) => {
this.actions[actionName](payLoad)
}
}
// vuex的插件使用方式:Vue.use(Vuex)
const install = (_Vue) => {
// 这里插件默认传入Vue构造函数,使用临时变量myVue进行接收,这样就不需要vuex库中再导入Vue库了
myVue = _Vue
// 核心点:借助`mixin`
// 将vue的store直接放在原型上,不对, 因为这样会导致所有的vue实例全部都有store属性;
// 这里只从当前根实例开始 所有根实例的子组件才有$store
myVue.mixin({
// 组件的创造过程先父后子
beforeCreate(){
// 把父组件的store属性,放到每个组件的实例上
if(this.$options.store){ // 根实例
this.$store = this.$options.store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export {
Store,
install
}
actions异步操作实现
借助Promise.all依次处理完所有的异步函数,并将处理之后的结果一起返回
// dispatch实现的是actions的异步操作(核心思想发布订阅)
dispatch方法在 (_type, _payload) {
// check object-style dispatch
const {
type,
payload
} = unifyObjectStyle(_type, _payload) // 配置参数处理
// entry是当前type下所有action处理函数集合
const entry = this._actions[type]
if (!entry) {
console.error(`[vuex] unknown action type: ${type}`)
return
}
// 当entry的函数个数大于1时,采用Promise.all,依次处理完所有的函数回调,然后将结果返回
return entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload)
}
// commit主要实现的mutations的同步操作(核心思想发布订阅)
commit (_type, _payload, _options) {
// check object-style commit
const {
type,
payload,
options
} = unifyObjectStyle(_type, _payload, _options)
const mutation = { type, payload }
const entry = this._mutations[type]
if (!entry) {
console.error(`[vuex] unknown mutation type: ${type}`)
return
}
// 专用修改state方法,其他修改state方法均是非法修改
this._withCommit(() => {
entry.forEach(function commitIterator (handler) {
handler(payload)
})
})
// 订阅者函数遍历执行,传入当前的mutation对象和当前的state
this._subscribers.forEach(sub => sub(mutation, this.state))
if (options && options.silent) {
console.warn(
`[vuex] mutation type: ${type}. Silent option has been removed. ` +
'Use the filter functionality in the vue-devtools'
)
}
}