解决了那些困惑
- 为什么组件能够通过 this.$store.state 访问到 vuex 注册的数据
- 执行 this.$store.commit() 能够触发 相应的 mutation 来更新 state
首先看一下,vuex 的基本使用
- 首先要下载插件,
Vue.use(vuex)
注册插件- 声明实例挂载到根组件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
new Vue({
el: '#app',
store: store,
})
- 然后可以在组件中访问
methods: {
increment() {
this.$store.commit('increment')
console.log(this.$store.state.count)
}
}
Vuex.use(vuex) 发生了什么
首先该方法是调用了插件的 install 方法
install 方法在目录 /src/store.js
export function install (_Vue) {
// 保证了插件只下载一次
if (Vue && _Vue === Vue) {
if (__DEV__) {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
Vue = _Vue
// 执行了初始化的方法,关键点
applyMixin(Vue)
}
然后查看 applyMixin 方法干了什么 (只取源码中核心代码), 能通过 this.$store.state 访问的关键
export default function(Vue) {
// 全局混入一个基本钩子函数,在每个组件实例构建前
// 执行 vuexInit 初始化函数
Vue.mixin({ beforeCreate: vuexInit})
function vuexInit () {
const options = this.$options
// store injection
// 给每个组件的 $store, 以便能够通过,this.$store.state 拿到值
// 做的操作就是,如果组件有 store 配置项,直接把 this.$store 赋值为 options.store, 没有的话就从父组件中取
if (options.store) {
this.$store = typeof options.store === 'function'
? options.store()
: options.store
} else if (options.parent && options.parent.$store) {
this.$store = options.parent.$store
}
}
}
执行 commiit 触发为什么可以触发响应的 mutation 更新 state
简化一下源码中的相关代码
export class Store {
constructor (options = {}) {
// 首先拿到实例中的 commit ,然后让调用本身的 commit 函数
const { commit } = this;
this.commit = function boundCommit (type, payload, options) {
return commit.call(store, type, payload, options)
}
}
commit (_type, _payload, _options) {
// 我猜 这句代码就是从 mutations 对象里面,拿到所有的 mutation
const entry = this._mutations[type]
// 执行 type 对应的 mutations
entry.forEach(function commitIterator (handler) {
handler(payload)
})
}
}
最基本的应该就是这个吧,源码还是得慢慢看,不能急啊,烦请过路大佬批评指正
这里附上vuex源码