<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                >PS:個人筆記,僅供參考,需要深入了解請閱讀參考資料。 [TOC] # 參考資料 [https://ustbhuangyi.github.io/vue-analysis/prepare/directory.html#sfc](https://ustbhuangyi.github.io/vue-analysis/prepare/directory.html#sfc) # Vuex 初始化 ## 安裝 和 Vue-Router 一樣,Vuex 也同樣存在一個靜態的`install`方法,它的定義在`src/store.js`中: ```js export function install (_Vue) { if (Vue && _Vue === Vue) { if (process.env.NODE_ENV !== 'production') { console.error( '[vuex] already installed. Vue.use(Vuex) should be called only once.' ) } return } Vue = _Vue applyMixin(Vue) } ``` `install`的邏輯很簡單,把傳入的`_Vue`賦值給`Vue`并執行了`applyMixin(Vue)`方法,它的定義在`src/mixin.js`中: ```js export default function (Vue) { const version = Number(Vue.version.split('.')[0]) if (version >= 2) { Vue.mixin({ beforeCreate: vuexInit }) } else { // override init and inject vuex init procedure // for 1.x backwards compatibility. const _init = Vue.prototype._init Vue.prototype._init = function (options = {}) { options.init = options.init ? [vuexInit].concat(options.init) : vuexInit _init.call(this, options) } } /** * Vuex init hook, injected into each instances init hooks list. */ function vuexInit () { const options = this.$options // store injection 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 } } } ``` `applyMixin`全局混入了一個`beforeCreate`鉤子函數,它的實現非常簡單,就是把`options.store`保存在所有組件的`this.$store`中,這個`options.store`就是`Store`對象的實例。 ## Store 實例化 我們在`import Vuex`之后,會實例化其中的`Store`對象,返回`store`實例并傳入`new Vue`的`options`中,也就是我們剛才提到的`options.store`.就像下面這樣: ```js export default new Vuex.Store({ actions, getters, state, mutations, modules // ... }) ``` `Store`對象的構造函數接收一個對象參數,它包含`actions`、`getters`、`state`、`mutations`、`modules`等 Vuex 的核心概念,它的定義在`src/store.js`中: ```js export class Store { constructor (options = {}) { // Auto install if it is not done yet and `window` has `Vue`. // To allow users to avoid auto-installation in some cases, // this code should be placed here. See #731 if (!Vue && typeof window !== 'undefined' && window.Vue) { install(window.Vue) } if (process.env.NODE_ENV !== 'production') { assert(Vue, `must call Vue.use(Vuex) before creating a store instance.`) assert(typeof Promise !== 'undefined', `vuex requires a Promise polyfill in this browser.`) assert(this instanceof Store, `Store must be called with the new operator.`) } const { plugins = [], strict = false } = options // store internal state this._committing = false this._actions = Object.create(null) this._actionSubscribers = [] this._mutations = Object.create(null) this._wrappedGetters = Object.create(null) this._modules = new ModuleCollection(options) this._modulesNamespaceMap = Object.create(null) this._subscribers = [] this._watcherVM = new Vue() // bind commit and dispatch to self const store = this const { dispatch, commit } = this this.dispatch = function boundDispatch (type, payload) { return dispatch.call(store, type, payload) } this.commit = function boundCommit (type, payload, options) { return commit.call(store, type, payload, options) } // strict mode this.strict = strict const state = this._modules.root.state // init root module. // this also recursively registers all sub-modules // and collects all module getters inside this._wrappedGetters installModule(this, state, [], this._modules.root) // initialize the store vm, which is responsible for the reactivity // (also registers _wrappedGetters as computed properties) resetStoreVM(this, state) // apply plugins plugins.forEach(plugin => plugin(this)) if (Vue.config.devtools) { devtoolPlugin(this) } } } ``` 這里有三個關鍵點: - 初始化模塊 ```js this._modules = new ModuleCollection(options) ``` - 安裝模塊 ```js // init root module. // this also recursively registers all sub-modules // and collects all module getters inside this._wrappedGetters installModule(this, state, [], this._modules.root) ``` - 初始化`store_.vm` ```js // initialize the store vm, which is responsible for the reactivity // (also registers _wrappedGetters as computed properties) resetStoreVM(this, state) ``` ### 初始化模塊 在分析模塊初始化之前,我們先來了解一下模塊對于 Vuex 的意義:由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象,當應用變得非常復雜時,`store`對象就有可能變得相當臃腫。為了解決以上問題,Vuex 允許我們將`store`分割成模塊(module)。每個模塊擁有自己的`state`、`mutation`、`action`、`getter`,甚至是嵌套子模塊——從上至下進行同樣方式的分割: ```js const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... }, } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的狀態 store.state.b // -> moduleB 的狀態 ``` `Module`是用來描述單個模塊的類,它的定義在`src/module/module.js`中: ```js export default class Module { constructor (rawModule, runtime) { this.runtime = runtime // Store some children item this._children = Object.create(null) // Store the origin module object which passed by programmer this._rawModule = rawModule const rawState = rawModule.state // Store the origin module's state this.state = (typeof rawState === 'function' ? rawState() : rawState) || {} } get namespaced () { return !!this._rawModule.namespaced } addChild (key, module) { this._children[key] = module } removeChild (key) { delete this._children[key] } getChild (key) { return this._children[key] } update (rawModule) { this._rawModule.namespaced = rawModule.namespaced if (rawModule.actions) { this._rawModule.actions = rawModule.actions } if (rawModule.mutations) { this._rawModule.mutations = rawModule.mutations } if (rawModule.getters) { this._rawModule.getters = rawModule.getters } } forEachChild (fn) { forEachValue(this._children, fn) } forEachGetter (fn) { if (this._rawModule.getters) { forEachValue(this._rawModule.getters, fn) } } forEachAction (fn) { if (this._rawModule.actions) { forEachValue(this._rawModule.actions, fn) } } forEachMutation (fn) { if (this._rawModule.mutations) { forEachValue(this._rawModule.mutations, fn) } } } ``` 對于每個模塊而言,`this._rawModule`表示模塊的配置,`this._children`表示它的所有子模塊,`this.state`表示這個模塊定義的`state`。 ### 安裝模塊 初始化模塊后,執行安裝模塊的相關邏輯,它的目標就是對模塊中的`state`、`getters`、`mutations`、`actions`做初始化工作 ```js function installModule (store, rootState, path, module, hot) { const isRoot = !path.length const namespace = store._modules.getNamespace(path) // register in namespace map if (module.namespaced) { store._modulesNamespaceMap[namespace] = module } // set state if (!isRoot && !hot) { const parentState = getNestedState(rootState, path.slice(0, -1)) const moduleName = path[path.length - 1] store._withCommit(() => { Vue.set(parentState, moduleName, module.state) }) } const local = module.context = makeLocalContext(store, namespace, path) module.forEachMutation((mutation, key) => { const namespacedType = namespace + key registerMutation(store, namespacedType, mutation, local) }) module.forEachAction((action, key) => { const type = action.root ? key : namespace + key const handler = action.handler || action registerAction(store, type, handler, local) }) module.forEachGetter((getter, key) => { const namespacedType = namespace + key registerGetter(store, namespacedType, getter, local) }) module.forEachChild((child, key) => { installModule(store, rootState, path.concat(key), child, hot) }) } ``` 這里涉及到了命名空間的概念,默認情況下,模塊內部的`action`、`mutation`和`getter`是注冊在全局命名空間的——這樣使得多個模塊能夠對同一`mutation`或`action`作出響應。如果我們希望模塊具有更高的封裝度和復用性,可以通過添加`namespaced: true`的方式使其成為帶命名空間的模塊。當模塊被注冊后,它的所有`getter`、`action`及`mutation`都會自動根據模塊注冊的路徑調整命名。 ### 初始化`store._vm` `Store`實例化的最后一步,就是執行初始化`store._vm`的邏輯,它的入口代碼是: ```js resetStoreVM(this, state) ``` ```js function resetStoreVM (store, state, hot) { const oldVm = store._vm // bind store public getters store.getters = {} const wrappedGetters = store._wrappedGetters const computed = {} forEachValue(wrappedGetters, (fn, key) => { // use computed to leverage its lazy-caching mechanism computed[key] = () => fn(store) Object.defineProperty(store.getters, key, { get: () => store._vm[key], enumerable: true // for local getters }) }) // use a Vue instance to store the state tree // suppress warnings just in case the user has added // some funky global mixins const silent = Vue.config.silent Vue.config.silent = true store._vm = new Vue({ data: { $$state: state }, computed }) Vue.config.silent = silent // enable strict mode for new vm if (store.strict) { enableStrictMode(store) } if (oldVm) { if (hot) { // dispatch changes in all subscribed watchers // to force getter re-evaluation for hot reloading. store._withCommit(() => { oldVm._data.$$state = null }) } Vue.nextTick(() => oldVm.$destroy()) } } ``` `resetStoreVM`的作用實際上是想建立`getters`和`state`的聯系,因為從設計上`getters`的獲取就依賴了`state`,并且希望它的依賴能被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。因此這里利用了 Vue 中用`computed`計算屬性來實現。 `resetStoreVM`首先遍歷了`_wrappedGetters`獲得每個`getter`的函數`fn`和`key`,然后定義了`computed[key] = () => fn(store)`。我們之前提到過`_wrappedGetters`的初始化過程,這里`fn(store)`相當于執行如下方法: ```js store._wrappedGetters[type] = function wrappedGetter (store) { return rawGetter( local.state, // local state local.getters, // local getters store.state, // root state store.getters // root getters ) } ``` 返回的就是`rawGetter`的執行函數,`rawGetter`就是用戶定義的`getter`函數,它的前 2 個參數是`local state`和`local getters`,后 2 個參數是`root state`和`root getters`。 接著實例化一個 Vue 實例`store._vm`,并把`computed`傳入: ```js store._vm = new Vue({ data: { $$state: state }, computed }) ``` 我們發現`data`選項里定義了`$$state`屬性,而我們訪問`store.state`的時候,實際上會訪問`Store`類上定義的`state`的`get`方法: ```js get state () { return this._vm._data.$$state } ``` 它實際上就訪問了`store._vm._data.$$state`。那么`getters`和`state`是如何建立依賴邏輯的呢,我們再看這段代碼邏輯: ```js forEachValue(wrappedGetters, (fn, key) => { // use computed to leverage its lazy-caching mechanism computed[key] = () => fn(store) Object.defineProperty(store.getters, key, { get: () => store._vm[key], enumerable: true // for local getters }) }) ``` ### 總結 我們要把`store`想象成一個數據倉庫,為了更方便的管理倉庫,我們把一個大的`store`拆成一些`modules`,整個`modules`是一個樹型結構。每個`module`又分別定義了`state`,`getters`,`mutations`、`actions`,我們也通過遞歸遍歷模塊的方式都完成了它們的初始化。為了`module`具有更高的封裝度和復用性,還定義了`namespace`的概念。最后我們還定義了一個內部的`Vue`實例,用來建立`state`到`getters`的聯系,并且可以在嚴格模式下監測`state`的變化是不是來自外部,確保改變`state`的唯一途徑就是顯式地提交`mutation`。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看