摘要:簡(jiǎn)單點(diǎn)說,當(dāng)你使用構(gòu)造函數(shù),它實(shí)際上做了這么幾件事,首先定義給實(shí)例定義一些內(nèi)部屬性,之后就是綁定和的上下文對(duì)象永遠(yuǎn)是實(shí)例上,之后根據(jù)傳入的充實(shí)內(nèi)部狀態(tài)等等。函數(shù)執(zhí)行的結(jié)果是返回一個(gè)對(duì)象,屬性名對(duì)應(yīng)于傳入的對(duì)象或者數(shù)組元素。
轉(zhuǎn)載請(qǐng)注明出處 https://segmentfault.com/a/11...
vuex2.0 和 vuex1.x 相比,API改變的還是很多的,但基本思想沒什么改變。vuex2.0 的源碼挺短,四五百行的樣子,兩三天就能讀完。我是國(guó)慶期間斷斷續(xù)續(xù)看完的,寫一下自己的理解。這里使用的vuex版本是 2.0.0-rc6。在看這篇文章之前,建議先看一遍官方的vuex2.0 文檔,了解基本概念,不然之后的內(nèi)容理解起來會(huì)很費(fèi)勁。
引入 vuex 文件要想使用 vuex 有幾種方式, 這里不細(xì)講。
CDN
ES6語(yǔ)法 + webpack
import Vuex from "vuex" var store = new Vuex.Store({}) Vuex.mapState({})
或者
import { Store, mapState } from "vuex" var store = new Store({}) mapState({})Store構(gòu)造函數(shù)
vuex 只暴露出了6個(gè)方法,分別是
var index = { Store: Store, install: install, mapState: mapState, mapMutations: mapMutations, mapGetters: mapGetters, mapActions: mapActions } return index;
其中 install 方法是配合 Vue.use 方法使用的,用于在 Vue 中注冊(cè) Vuex ,和數(shù)據(jù)流關(guān)系不大。其他的幾種方法就是我們常用的。
先看看 Store 方法,學(xué)習(xí) vuex 最先接觸到的就是 new Store({}) 了。那么就先看看這個(gè) Store 構(gòu)造函數(shù)。
var Store = function Store (options) { var this$1 = this; // 指向返回的store實(shí)例 if ( options === void 0 ) options = {}; // 使用構(gòu)造函數(shù)之前,必須保證vuex已注冊(cè),使用Vue.use(Vuex)注冊(cè)vuex assert(Vue, "must call Vue.use(Vuex) before creating a store instance.") // 需要使用的瀏覽器支持Promise assert(typeof Promise !== "undefined", "vuex requires a Promise polyfill in this browser.") var state = options.state; if ( state === void 0 ) state = {}; var plugins = options.plugins; if ( plugins === void 0 ) plugins = []; var strict = options.strict; if ( strict === void 0 ) strict = false; // store internal state // store的內(nèi)部狀態(tài)(屬性) this._options = options this._committing = false this._actions = Object.create(null) // 保存actions this._mutations = Object.create(null) // 保存mutations this._wrappedGetters = Object.create(null) // 保存包裝后的getters this._runtimeModules = Object.create(null) this._subscribers = [] this._watcherVM = new Vue() // bind commit and dispatch to self var store = this var ref = this; var dispatch = ref.dispatch; // 引用的是Store.prototype.dispatch var commit = ref.commit; // 引用的是Store.prototype.commit this.dispatch = function boundDispatch (type, payload) { // 綁定上下文對(duì)象 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 // 是否開啟嚴(yán)格模式 // init root module. // this also recursively registers all sub-modules // and collects all module getters inside this._wrappedGetters // 初始化 root module // 同時(shí)也會(huì)遞歸初始化所有子module // 并且收集所有的getters至this._wrappedGetters installModule(this, state, [], options) // initialize the store vm, which is responsible for the reactivity // (also registers _wrappedGetters as computed properties) // 重置vm實(shí)例狀態(tài) // 同時(shí)在這里把getters轉(zhuǎn)化為computed(計(jì)算屬性) resetStoreVM(this, state) // apply plugins plugins.concat(devtoolPlugin).forEach(function (plugin) { return plugin(this$1); }) };
一開始會(huì)有兩個(gè)判斷條件,判斷 vuex 是否已經(jīng)注冊(cè),和當(dāng)前瀏覽器是否支持 Promise, assert 方法也挺簡(jiǎn)單,如果傳入的第一個(gè)參數(shù)為假值,則拋出一個(gè)錯(cuò)誤。
function assert (condition, msg) { if (!condition) { throw new Error(("[vuex] " + msg)) } }
接著往下看,接著會(huì)定義 state, plugins,strict三個(gè)變量,分別是你傳入的 options 對(duì)應(yīng)的選項(xiàng)。之后就是定義返回的 store 實(shí)例的一些內(nèi)部狀態(tài)。先不要管它們具體是什么,這個(gè)之后會(huì)慢慢講,這里先看看 Store 構(gòu)造函數(shù)都做了些什么。再之后就是綁定 dispatch 和 commit 方法到 store 實(shí)例上。接下來就是整個(gè) vuex 的核心方法 installModule 了,之后重置 vm 實(shí)例的狀態(tài)。
簡(jiǎn)單點(diǎn)說,當(dāng)你使用 Store 構(gòu)造函數(shù),它實(shí)際上做了這么幾件事,首先定義給 store 實(shí)例定義一些內(nèi)部屬性,之后就是綁定 dispatch 和 commit 的上下文對(duì)象永遠(yuǎn)是 store 實(shí)例上,之后 installModule 根據(jù)傳入的 options ‘充實(shí)’ 內(nèi)部狀態(tài)等等。
installModule很重要的一個(gè)方法。貼上代碼
/* * store 就是 store 實(shí)例 * rootState 是使用構(gòu)造函數(shù)options中定義的 state 對(duì)象 * path 路徑 * module 傳入的options */ function installModule (store, rootState, path, module, hot) { var isRoot = !path.length // 是否是root var state = module.state; var actions = module.actions; var mutations = module.mutations; var getters = module.getters; var modules = module.modules; // set state if (!isRoot && !hot) { // 找到要注冊(cè)的 path 的上一級(jí) state var parentState = getNestedState(rootState, path.slice(0, -1)) // 定義 module 的 name var moduleName = path[path.length - 1] // store._withCommit方法之后會(huì)講 // 這里先理解為 執(zhí)行傳入的函數(shù) store._withCommit(function () { // 使用Vue.set方法 // parentState[moduleName] = state // 并且state變成響應(yīng)式的 Vue.set(parentState, moduleName, state || {}) }) } // 之后設(shè)置 mutations, actions, getters, modules if (mutations) { Object.keys(mutations).forEach(function (key) { registerMutation(store, key, mutations[key], path) }) } if (actions) { Object.keys(actions).forEach(function (key) { registerAction(store, key, actions[key], path) }) } if (getters) { wrapGetters(store, getters, path) } if (modules) { Object.keys(modules).forEach(function (key) { installModule(store, rootState, path.concat(key), modules[key], hot) }) } }
這里有個(gè)很重要的概念要理解,什么是 path. vuex 的一個(gè) store 實(shí)例可以拆分成很多個(gè) module ,不同的 module 可以理解成一個(gè)子代的 store 實(shí)例(事實(shí)上,module 確實(shí)和 store 具有一樣的結(jié)構(gòu)),這是一種模塊化的概念。因此這里的 path 可以理解成是表示一種層級(jí)關(guān)系,當(dāng)你有了一個(gè) root state 之后,根據(jù)這個(gè) root state 和 path 可以找到 path 路徑對(duì)應(yīng)的一個(gè) local state, 每一個(gè) module 下的 mutations 和 actions 改變的都是這個(gè)local state,而不是 root state.
這里在 Store 構(gòu)造函數(shù)里傳入的 path 路徑為 [],說明注冊(cè)的是一個(gè)root state. 再看看上一段代碼的最后
if (modules) { Object.keys(modules).forEach(function (key) { installModule(store, rootState, path.concat(key), modules[key], hot) }) }
如果傳入的options 中有 modules 選項(xiàng),重復(fù)調(diào)用 installModule, 這里傳入的函數(shù)的 path 參數(shù)是 path.concat(key), 所以應(yīng)該很好理解了。
簡(jiǎn)單看一下 getNestedState 方法。
/* * state: Object, path: Array * 假設(shè)path = ["a", "b", "c"] * 函數(shù)返回結(jié)果是state[a][b][c] */ function getNestedState (state, path) { return path.length ? path.reduce(function (state, key) { return state[key]; }, state) : state }
reduce 方法接受一個(gè)函數(shù),函數(shù)的參數(shù)分別是上一次計(jì)算后的值,和當(dāng)前值,reduce 方法的第二個(gè)參數(shù) state 是初始計(jì)算值。
registerMutation如果 mutations 選項(xiàng)存在,那么就注冊(cè)這個(gè) mutations ,看一下它的實(shí)現(xiàn)。
/* * 注冊(cè)mutations,也就是給store._mutations添加屬性 * 這里說一下handler * handler 是 mutations[key] * 也就是傳入 Store構(gòu)造函數(shù)的 mutations */ function registerMutation (store, type, handler, path) { if ( path === void 0 ) path = []; // 在_mutations中找到對(duì)應(yīng)type的mutation數(shù)組 // 如果是第一次創(chuàng)建,就初始化為一個(gè)空數(shù)組 var entry = store._mutations[type] || (store._mutations[type] = []) // 推入一個(gè)對(duì)原始mutations[key]包裝過的函數(shù) entry.push(function wrappedMutationHandler (payload) { // store.state表示root state, 先獲取path路徑下的local state // mutation應(yīng)該是對(duì)path路徑下的state的修改 // 函數(shù)接受一個(gè)payload參數(shù) // 初始的handler,接受一個(gè)state he payload 參數(shù) handler(getNestedState(store.state, path), payload) }) }
邏輯很簡(jiǎn)單,所有的 mutations 都經(jīng)過處理后,保存在了 store._mutations 對(duì)象里。 _mutations 的結(jié)構(gòu)為
_mutations: { type1: [wrappedFunction1, wrappedFuction2, ...], type2: [wrappedFunction1, wrappedFuction2, ...], ... }registerAction
function registerAction (store, type, handler, path) { if ( path === void 0 ) path = []; var entry = store._actions[type] || (store._actions[type] = []) var dispatch = store.dispatch; var commit = store.commit; entry.push(function wrappedActionHandler (payload, cb) { var res = handler({ dispatch: dispatch, commit: commit, getters: store.getters, state: getNestedState(store.state, path), rootState: store.state }, payload, cb) // 如果 res 不是 promise 對(duì)象 ,將其轉(zhuǎn)化為promise對(duì)象 // 這是因?yàn)閟tore.dispatch 方法里的 Promise.all()方法。 if (!isPromise(res)) { res = Promise.resolve(res) } if (store._devtoolHook) { return res.catch(function (err) { store._devtoolHook.emit("vuex:error", err) throw err }) } else { return res } }) }
這里同樣是"充實(shí)" store._actions 對(duì)象,每一種 action type 都對(duì)應(yīng)一個(gè)數(shù)組,數(shù)組里存放的包裝后的 handler 函數(shù),由于涉及到 promise,這里我想在下一節(jié)結(jié)合 store 的 dispatch 實(shí)例方法一起講。
wrapGetters/* * 包裝getters函數(shù) * store增加一個(gè) _wrappedGetters 屬性 * moduleGetters: 傳入的options.getters * modulePath: 傳入 installModule 函數(shù)的 path */ function wrapGetters (store, moduleGetters, modulePath) { Object.keys(moduleGetters).forEach(function (getterKey) { var rawGetter = moduleGetters[getterKey] // 原始的getter if (store._wrappedGetters[getterKey]) { // 如果已經(jīng)存在,警告 console.error(("[vuex] duplicate getter key: " + getterKey)) return } store._wrappedGetters[getterKey] = function wrappedGetter (store) { // 接受三個(gè)參數(shù) // local state // 全局的 getters // 全局的 state return rawGetter( getNestedState(store.state, modulePath), // local state store.getters, // getters store.state // root state ) } }) }
注意 這里的所有 getters 都儲(chǔ)存在了全局的一個(gè) _wrappedGetters 對(duì)象中,同樣屬性名是各個(gè) getterKey ,屬性值同樣是一個(gè)函數(shù),執(zhí)行這個(gè)函數(shù),將會(huì)返回原始 getter 的執(zhí)行結(jié)果。
install modulesif (modules) { Object.keys(modules).forEach(function (key) { installModule(store, rootState, path.concat(key), modules[key], hot) }) }
如果 options 中有 modules 選項(xiàng),那么就遞歸調(diào)用 installModule 方法,注意這里的 path 改變。
resetStoreVMfunction resetStoreVM (store, state) { var oldVm = store._vm // 原來的_vm // bind store public getters store.getters = {} // 初始化 store 的 getters 屬性為一個(gè)空數(shù)組。 var wrappedGetters = store._wrappedGetters var computed = {} Object.keys(wrappedGetters).forEach(function (key) { var fn = wrappedGetters[key] // use computed to leverage its lazy-caching mechanism // 將wrappedGetter中的屬性轉(zhuǎn)移到 computed 中 computed[key] = function () { return fn(store); } // store.getters[key] = store._vm[key] Object.defineProperty(store.getters, key, { get: function () { return store._vm[key]; } }) }) // use a Vue instance to store the state tree // suppress warnings just in case the user has added // some funky global mixins // 設(shè)為 silent 模式 var silent = Vue.config.silent Vue.config.silent = true // 初始化一個(gè) store._vm 實(shí)例 store._vm = new Vue({ data: { state: state }, computed: computed }) Vue.config.silent = silent // enable strict mode for new vm // 啟用嚴(yán)格模式 if (store.strict) { enableStrictMode(store) } if (oldVm) { // dispatch changes in all subscribed watchers // to force getter re-evaluation. store._withCommit(function () { oldVm.state = null }) // 執(zhí)行destroy 方法,通知所有的watchers 改變,并重新計(jì)算getters的值。 Vue.nextTick(function () { return oldVm.$destroy(); }) } }
這個(gè)方法在 installModule 方法之后執(zhí)行,來看看它都做了什么。簡(jiǎn)單點(diǎn)說,就是給 store 增加了一個(gè) _vm 屬性,指向一個(gè)新的 vue 實(shí)例,傳入的選項(xiàng)包括一個(gè) state 和 computed, computed 來自store 的 getters 屬性。同時(shí)給 store 增加了一個(gè) getters 屬性,且 store.getters[key] = store._vm[key]
mapState在講 mapState 之前,先說一下基礎(chǔ)方法 normalizeMap
/* * 如果map是一個(gè)數(shù)組 ["type1", "type2", ...] * 轉(zhuǎn)化為[ * { * key: type1, * val: type1 * }, * { * key: type2, * val: type2 * }, * ... * ] * 如果map是一個(gè)對(duì)象 {type1: fn1, type2: fn2, ...} * 轉(zhuǎn)化為 [ * { * key: type1, * val: fn1 * }, * { * key: type2, * val: fn2 * }, * ... * ] */ function normalizeMap (map) { return Array.isArray(map) ? map.map(function (key) { return ({ key: key, val: key }); }) : Object.keys(map).map(function (key) { return ({ key: key, val: map[key] }); }) }
normalizeMap 函數(shù)接受一個(gè)對(duì)象或者數(shù)組,最后都轉(zhuǎn)化成一個(gè)數(shù)組形式,數(shù)組元素是包含 key 和 value 兩個(gè)屬性的對(duì)象。
再來看看 mapState 方法。
/* * states: Object | Array * 返回一個(gè)對(duì)象 * 對(duì)象的屬性名對(duì)應(yīng)于傳入的 states 的屬性名或者數(shù)組元素 * 屬性值都是一個(gè)函數(shù) * 執(zhí)行這個(gè)函數(shù)的返回值根據(jù) val 的不同而不同 */ function mapState (states) { var res = {} normalizeMap(states).forEach(function (ref) { var key = ref.key; var val = ref.val; res[key] = function mappedState () { return typeof val === "function" // 如果是函數(shù),返回函數(shù)執(zhí)行后的結(jié)果 ? val.call(this, this.$store.state, this.$store.getters) : this.$store.state[val] // 如果不是函數(shù),而是一個(gè)字符串,直接在state中讀取。 } }) return res }
mapState 函數(shù)執(zhí)行的結(jié)果是返回一個(gè)對(duì)象,屬性名對(duì)應(yīng)于傳入的 states 對(duì)象或者數(shù)組元素。屬性值是一個(gè)函數(shù),執(zhí)行這個(gè)函數(shù)將返回相應(yīng)的 state .
mapMutations/* * mutations: Array * 返回一個(gè)對(duì)象 * 屬性名為 mutation 類型 * 屬性值為一個(gè)函數(shù) * 執(zhí)行這個(gè)函數(shù)后將觸發(fā)指定的 mutation */ function mapMutations (mutations) { var res = {} normalizeMap(mutations).forEach(function (ref) { var key = ref.key; // mutation type var val = ref.val; // mutation type res[key] = function mappedMutation () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; // 一個(gè)數(shù)組緩存?zhèn)魅氲膮?shù) // val作為commit函數(shù)的第一個(gè)參數(shù)type, 剩下的參數(shù)依次是payload 和 options return this.$store.commit.apply(this.$store, [val].concat(args)) } }) return res }
注意這里傳入的 mutations 只能是一個(gè)數(shù)組,數(shù)組元素的 mutation type . 函數(shù)的作用的也很簡(jiǎn)單,傳入一個(gè) mutations 數(shù)組,返回一個(gè)對(duì)象,屬性名是 mutation 的類型,屬性值是一個(gè)函數(shù),執(zhí)行這個(gè)函數(shù),將調(diào)用 commit 來觸發(fā)對(duì)應(yīng)的 mutation 從而改變state。另外注意這里的 this 指向的 store 的 _vm 。mapState 是在 Vue 實(shí)例中調(diào)用的。
mapActionsfunction mapActions (actions) { var res = {} normalizeMap(actions).forEach(function (ref) { var key = ref.key; var val = ref.val; res[key] = function mappedAction () { var args = [], len = arguments.length; while ( len-- ) args[ len ] = arguments[ len ]; return this.$store.dispatch.apply(this.$store, [val].concat(args)) } }) return res }
mapActions 函數(shù)和 mapMutations 函數(shù)幾乎如出一轍。唯一的區(qū)別即使這里應(yīng)該使用 dispatch 方法來觸發(fā) action.
mapGetters/* * getters: Array */ function mapGetters (getters) { var res = {} normalizeMap(getters).forEach(function (ref) { var key = ref.key; var val = ref.val; res[key] = function mappedGetter () { // 如果在getters中不存在,報(bào)錯(cuò) if (!(val in this.$store.getters)) { console.error(("[vuex] unknown getter: " + val)) } // 根據(jù) val 在 getters 對(duì)象里找對(duì)應(yīng)的屬性值 return this.$store.getters[val] } }) return res }
這里 getters 同樣接受一個(gè)數(shù)組,同樣返回一個(gè)對(duì)象。
以上講了四種 map*** 方法,這四種方法可以都返回一個(gè)對(duì)象,因此可以 ES6 新特性 ... 解構(gòu)符。如
{ ...mapState(options) }
關(guān)于 ... 解構(gòu)符號(hào), 舉個(gè)小例子就明白了
var obj1 = { a: 1, b: 2, c: 3 } var obj2 = { ...obj1, d: 4 } // obj2 = { a: 1, b: 2, c: 3, d: 4 } // 同樣可以用于數(shù)組 var arr1 = ["a", "b", "c"] var arr2 = [...arr1, "d"] // arr2 = ["a", "b", "c", "d"]install
install 方法與 vuex 數(shù)據(jù)流關(guān)系不大,主要是用于在 Vue 中注冊(cè) Vuex,這里為了保持篇幅的完整性,簡(jiǎn)單介紹一下。
function install (_Vue) { if (Vue) { // 報(bào)錯(cuò),已經(jīng)使用了 Vue.use(Vuex)方法注冊(cè)了 console.error( "[vuex] already installed. Vue.use(Vuex) should be called only once." ) return } Vue = _Vue applyMixin(Vue) } // auto install in dist mode // 在瀏覽器環(huán)境寫,會(huì)自動(dòng)調(diào)用 install 方法 if (typeof window !== "undefined" && window.Vue) { install(window.Vue) }
沒什么難度,那就再看一下 applyMixin 方法
function applyMixin (Vue) { var version = Number(Vue.version.split(".")[0]) // 檢查使用的 Vue 版本,初始化時(shí)的生命周期鉤子函數(shù)是 init 還是 beforeCreate if (version >= 2) { var usesInit = Vue.config._lifecycleHooks.indexOf("init") > -1 Vue.mixin(usesInit ? { init: vuexInit } : { beforeCreate: vuexInit }) } else { // override init and inject vuex init procedure // for 1.x backwards compatibility. // 保存之前的 Vue.prototype._init var _init = Vue.prototype._init // 重新設(shè)置Vue.prototype._init Vue.prototype._init = function (options) { if ( options === void 0 ) options = {}; // 初始化時(shí)先初始化vuexInit // options.init: Array 表示一組要執(zhí)行的鉤子函數(shù) // options.init鉤子函數(shù)之前加上了 vueInit 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 () { var options = this.$options // store injection // 如果自己有store選項(xiàng),用自己的 // 否則查找父組件的 if (options.store) { this.$store = options.store } else if (options.parent && options.parent.$store) { this.$store = options.parent.$store } } }
注釋寫的很清楚了,那么再看看什么有是 vuexInit 函數(shù), vuexInit 函數(shù)是 vuex 的生命周期鉤子函數(shù)。函數(shù)傳遞了兩個(gè)信息,(1)子組件可以有自己多帶帶的store,但是一般不這么做 (2) 如果子組件沒有自己的 store ,就會(huì)查找父組件的。這也印證了 根組件的 store 會(huì)注入到所有的后代組件。
小結(jié)以上講解了 Vuex 暴露出的 6 種方法,也是 Vuex 里的用的最多的幾種方法,之后還會(huì)解讀一下其他一些方法,比如 store 的一些實(shí)例方法。
另外本文的 github 的地址為: learnVuex2.0
轉(zhuǎn)載請(qǐng)注明原鏈接
全文完
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80628.html
摘要:至此它便作為一個(gè)唯一數(shù)據(jù)源而存在。改變中的狀態(tài)的唯一途徑就是顯式地提交。這樣使得可以方便地跟蹤每一個(gè)狀態(tài)的變化,從而能夠?qū)崿F(xiàn)一些工具幫助更好地了解應(yīng)用背后的基本思想,借鑒了和參考源碼解讀一架構(gòu)入門教程狀態(tài)管理 準(zhǔn)備工作 1.下載安裝運(yùn)行 這里以2.0.0-rc.6為例官網(wǎng)github下載鏈接(對(duì)應(yīng)版本):https://github.com/vuejs/vuex...點(diǎn)擊下載到本地 ...
摘要:第一篇文章我會(huì)結(jié)合和的部分源碼,來說明注入生命周期的過程。說到源碼,其實(shí)沒有想象的那么難。但是源碼的調(diào)用樹會(huì)復(fù)雜很多。應(yīng)用的業(yè)務(wù)代碼逐漸復(fù)雜,事件事件總線等通信的方式的弊端就會(huì)愈發(fā)明顯。狀態(tài)管理是組件解耦的重要手段。前言 這篇文章是【前端詞典】系列文章的第 13 篇文章,接下的 9 篇我會(huì)圍繞著 Vue 展開,希望這 9 篇文章可以使大家加深對(duì) Vue 的了解。當(dāng)然這些文章的前提是默認(rèn)你對(duì) ...
摘要:無(wú)需使用服務(wù)器實(shí)時(shí)動(dòng)態(tài)編譯,而是使用預(yù)渲染方式,在構(gòu)建時(shí)簡(jiǎn)單地生成針對(duì)特定路由的靜態(tài)文件。與可以部署在任何靜態(tài)文件服務(wù)器上的完全靜態(tài)單頁(yè)面應(yīng)用程序不同,服務(wù)器渲染應(yīng)用程序,需要處于運(yùn)行環(huán)境。更多的服務(wù)器端負(fù)載。 目錄結(jié)構(gòu) -no-ssr-demo 未做ssr之前的項(xiàng)目代碼用于對(duì)比 -vuecli2ssr 將vuecli生成的項(xiàng)目轉(zhuǎn)為ssr -prerender-demo 使用prer...
摘要:個(gè)人看來,一個(gè)狀態(tài)管理的應(yīng)用,無(wú)論是使用,還是,最困難的部分是在的設(shè)計(jì)。中,并沒有移除,而是改為用于觸發(fā)。也是一個(gè)對(duì)象,用于注冊(cè),每個(gè)都是一個(gè)用于返回一部分的。接受一個(gè)數(shù)組或?qū)ο?,根?jù)相應(yīng)的值將對(duì)應(yīng)的綁定到組件上。 系列文章: Vue 2.0 升(cai)級(jí)(keng)之旅 Vuex — The core of Vue application (本文) 從單頁(yè)應(yīng)用(SPA)到服務(wù)器...
摘要:學(xué)習(xí),首先明白是什么是一個(gè)專為應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。 學(xué)習(xí)vuex,首先明白vuex是什么?Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。 如果你在使用 vue.js , 那么我...
閱讀 1823·2019-08-30 13:54
閱讀 2737·2019-08-29 17:27
閱讀 1125·2019-08-29 17:23
閱讀 3362·2019-08-29 15:20
閱讀 1237·2019-08-29 11:28
閱讀 1580·2019-08-26 10:39
閱讀 1327·2019-08-26 10:29
閱讀 653·2019-08-26 10:13