index.js
index 文件夾主要是爲了導出vuex提供的模塊
import { Store, install } from './store'
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from './helpers'
`export default {`
`Store,`// Store:包含狀態的容器`
`install,`// install: 提供給Vue.use()全局掛載的install`
`version: '__VERSION__',`
`mapState,`// mapState: 展開state的內容`
`mapMutations,`// mapMutations:展開mutations的內容`
`mapGetters,`// mapGetters:展開getter的內容`
`mapActions,`// mapActions:展開actions的內容`
`createNamespacedHelpers`// createNamespacedHelpers:創建基於命名空間的組件綁定輔助函數`
}
store.js中的 install函數
我們在使用vuex的時候是vue.use(vuex),這個是怎麼實現的呢?
- vue的插件系統,提供了use函數,方便我們引入插件
- use函數規定,每個插件都需要編寫install函數,vuex在store.js中提供了install函數
// 這裏的_vue是一個全局變量,用來接收vue
// vue使用插件的方法很簡單,只需Vue.use(Plugins)即可使用插件。在vue中是如何實現的呢?
// 瞭解vue的話,你應該知道,use(),接收一個install方法,這個install由插件開發者定義。
// 最後達到全局註冊組件。
export function install(_Vue) {
// 判斷已經引入過插件。防止重複引入。其實在vue.use中也會判斷時候已經裝過
if (Vue && _Vue === Vue) {
if (process.env.NODE_ENV !== 'production') {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
// 如果沒有引入,調用applyMixin().此方法位於mixin.js
Vue = _Vue
applyMixin(Vue)
}
install函數調用applyMixin().此方法位於mixin.js
// 執行vuexInit方法初始化Vuex
// 這裏針對Vue1.0與2.0分別進行了不同的處理
// Vue1.0,Vuex會將vuexInit方法放入Vue的_init方法中,
// Vue2.0,則會將vuexinit混淆進Vue的beforeCreate鉤子中。
export default function (Vue) {
//獲取vue的版本
const version = Number(Vue.version.split('.')[0])
// 如果vue的版本大於2的話,直接調用vuexInit放入beforeCreate鉤子中
if (version >= 2) {
// 使用mixin方法,在組件創建前加入vuexInit
Vue.mixin({ beforeCreate: vuexInit })
} else {
// 重寫init,將vuexInit放入init中
// 先把Vue.prototype._init存放在常量中,防止修改
const _init = Vue.prototype._init
Vue.prototype._init = function (options = {}) {
options.init = options.init
? [vuexInit].concat(options.init)
: vuexInit
_init.call(this, options)
}
}
// 在 vuexInit 中,將 new Vue() 時傳入的 store 設置到 this 對象的 $store 屬性上,//
// !!!
// 注意,因爲每個組件都會被渲染,在上面使用mixin進行了混入,所以vuexInit在組件被創建之前都會被調用。
// vue渲染組件的方法是先渲染父組件在渲染子組件,深度優先。
// new Vue() 時傳入的 store,這個時候,store已經掛在最上面的root(根)組件上。
// 子組件則從其父組件上引用其 $store 屬性進行層層嵌套設置,保證每一個組件中都可以通過 this.$store 取到 store 對象。
// 通過在根實例中註冊 store 選項,該 store 實例會注入到根組件下的所有子組件中,注入方法是子從父拿,root從options拿。
function vuexInit() {
// vue 提供的一個實例屬性,用來獲取Vue實例的自定義屬性(如vm.$options.methods,獲取Vue實例的自定義屬性methods)
const options = this.$options
// 如果 new Vue() 時傳入了 store
// 如果本身就是父組件
if (options.store) {
// 則將store掛在到this上,也就是vue上
this.$store = typeof options.store === 'function'
? options.store()
: options.store
} else if (options.parent && options.parent.$store) {
// 如果某個組件存在父級組件,並且父級組件存在$store,則將該組件上也掛載$store
this.$store = options.parent.$store
}
}
}