成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

vuex 2.0源碼解讀(一)

luqiuwen / 1029人閱讀

摘要:簡(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ù)都做了些什么。再之后就是綁定 dispatchcommit 方法到 store 實(shí)例上。接下來就是整個(gè) vuex 的核心方法 installModule 了,之后重置 vm 實(shí)例的狀態(tài)。

簡(jiǎn)單點(diǎn)說,當(dāng)你使用 Store 構(gòu)造函數(shù),它實(shí)際上做了這么幾件事,首先定義給 store 實(shí)例定義一些內(nèi)部屬性,之后就是綁定 dispatchcommit 的上下文對(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 modules
if (modules) {
    Object.keys(modules).forEach(function (key) {
      installModule(store, rootState, path.concat(key), modules[key], hot)
   })
 }

如果 options 中有 modules 選項(xiàng),那么就遞歸調(diào)用 installModule 方法,注意這里的 path 改變。

resetStoreVM
function 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 的 _vmmapState 是在 Vue 實(shí)例中調(diào)用的。

mapActions
function 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

相關(guān)文章

  • vuex 2.0 源碼解讀

    摘要:至此它便作為一個(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)擊下載到本地 ...

    yvonne 評(píng)論0 收藏0
  • 【前端詞典】從源碼解讀 Vuex 注入 Vue 生命周期的過程

    摘要:第一篇文章我會(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ì) ...

    Aklman 評(píng)論0 收藏0
  • vue服務(wù)端渲染demo將vue-cli生成的項(xiàng)目轉(zhuǎn)為ssr

    摘要:無(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...

    whinc 評(píng)論0 收藏0
  • Vuex — The core of Vue application

    摘要:個(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ù)器...

    Aldous 評(píng)論0 收藏0
  • vuex入門,詳細(xì)的講解

    摘要:學(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 , 那么我...

    jsummer 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<