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
}
}
}