vuex的五個屬性

Vuex是什么凯傲?

VueX 是一個專門為 Vue.js 應(yīng)用設(shè)計的狀態(tài)管理架構(gòu)冰单,統(tǒng)一管理和維護各個vue組件的可變化狀態(tài)(你可以理解成 vue 組件里的某些 data )球凰。

Vue有五個核心概念腿宰,state, getters, mutations, actions, modules吃度。本文將對這個五個核心概念進行梳理椿每。

總結(jié)

state => 基本數(shù)據(jù)
getters => 從基本數(shù)據(jù)派生的數(shù)據(jù)
mutations => 提交更改數(shù)據(jù)的方法英遭,同步!
actions => 像一個裝飾器汁尺,包裹mutations痴突,使之可以異步辽装。
modules => 模塊化Vuex

State

state即Vuex中的基本數(shù)據(jù)拾积!
單一狀態(tài)樹
Vuex使用單一狀態(tài)樹,即用一個對象就包含了全部的狀態(tài)數(shù)據(jù)此再。state作為構(gòu)造器選項输拇,定義了所有我們需要的基本狀態(tài)參數(shù)策吠。
在Vue組件中獲得Vuex屬性

  • 我們可以通過Vue的Computed獲得Vuex的state猴抹,如下:
const store = new Vuex.Store({
    state: {
        count:0
    }
})
const app = new Vue({
    //..
    store,
    computed: {
        count: function(){
            return this.$store.state.count
        }
    },
    //..
})

每當 store.state.count 變化的時候, 都會重新求取計算屬性蟀给,并且觸發(fā)更新相關(guān)聯(lián)的 DOM跋理。
mapState輔助函數(shù)
當一個組件需要獲取多個狀態(tài)時候,將這些狀態(tài)都聲明為計算屬性會有些重復(fù)和冗余拭卿。為了解決這個問題贱纠,我們可以使用 mapState 輔助函數(shù)幫助我們生成計算屬性谆焊,讓你少按幾次鍵。

// 在單獨構(gòu)建的版本中輔助函數(shù)為 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭頭函數(shù)可使代碼更簡練
    count: state => state.count,

    // 傳字符串參數(shù) 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 為了能夠使用 `this` 獲取局部狀態(tài)军拟,必須使用常規(guī)函數(shù)
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

當映射的計算屬性的名稱與 state 的子節(jié)點名稱相同時懈息,我們也可以給 mapState 傳一個字符串數(shù)組辫继。

computed: mapState([
  // 映射 this.count 為 store.state.count
  'count'
])

對象展開運算符
mapState 函數(shù)返回的是一個對象姑宽。我們?nèi)绾螌⑺c局部計算屬性混合使用呢炮车?通常瘦穆,我們需要使用一個工具函數(shù)將多個對象合并為一個,以使我們可以將最終對象傳給 computed 屬性熙兔。但是自從有了對象展開運算符住涉,我們可以極大地簡化寫法:

computed: {
  localComputed () //本地計算屬性
  //使用對象展開運算符將此對象混入到外部對象中
  ...mapState({
    //..
  })
}

對象運算符

... 展開運算符(spread operator)允許一個表達式在某處展開秆吵。展開運算符在多個參數(shù)(用于函數(shù)調(diào)用)或多個元素(用于數(shù)組字面量)或者多個變量(用于解構(gòu)賦值)的地方可以使用。

展開運算符不能用在對象當中泻拦,因為目前展開運算符只能在可遍歷對象(iterables)可用。iterables的實現(xiàn)是依靠[Symbol.iterator]函數(shù)架曹,而目前只有Array,Set,String內(nèi)置[Symbol.iterator]方法隘冲,而Object尚未內(nèi)置該方法,因此無法使用展開運算符绑雄。不過ES7草案當中已經(jīng)加入了對象展開運算符特性展辞。

function test(a,b,c) {
        console.log(a);
        console.log(b);
        console.log(c);
    }
    var args = [0,1,2];
    test(...args);  // 0  1  2

ES7草案中的對象展開運算符

ES6中還不支持對對象的展開運算符,但是ES7中將支持万牺。對象展開運算符符可以讓我們更快捷地操作對象罗珍,如下例子:

let {x,y,...z}={x:1,y:2,a:3,b:4};
    x; //1
    y; //2
    z; //{a:3,b:4}

組件仍然保有局部狀態(tài)
使用 Vuex 并不意味著你需要將所有的狀態(tài)放入 Vuex。雖然將所有的狀態(tài)放到 Vuex 會使狀態(tài)變化更顯式和易調(diào)試脚粟,但也會使代碼變得冗長和不直觀覆旱。

如果有些狀態(tài)嚴格屬于單個組件团南,最好還是作為組件的局部狀態(tài)。你應(yīng)該根據(jù)你的應(yīng)用開發(fā)需要進行權(quán)衡和確定朋腋。

getters

即從store的state中派生出的狀態(tài)。
getters接收state作為其第一個參數(shù)仲墨,接受其他 getters 作為第二個參數(shù)癌蚁,如不需要伐蒂,第二個參數(shù)可以省略如下例子:

const store = new Vuex.Store({
    state: {
        count:0
    }昭雌,
    getters: {
        // 單個參數(shù)
        countDouble: function(state){
            return state.count * 2
        },
        // 兩個參數(shù)
        countDoubleAndDouble: function(state, getters) {
            return getters.countDouble * 2
        }
    }
})

與state一樣呈宇,我們也可以通過Vue的Computed獲得Vuex的getters炬搭。

const app = new Vue({
    //..
    store,
    computed: {
        count: function(){
            return this.$store.state.count
        },
        countDouble: function(){
            return this.$store.getters.countDouble
        },
        countDoubleAndDouble: function(){
            return this.$store.getters.countDoubleAndDouble
        }
    },
    //..
})

mapGetters 輔助函數(shù)
mapGetters 輔助函數(shù)僅僅是將 store 中的 getters 映射到局部計算屬性有额,與state類似

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用對象展開運算符將 getters 混入 computed 對象中
    ...mapGetters([
      'countDouble',
      'CountDoubleAndDouble',
      //..
    ])
  }
}

如果你想將一個 getter 屬性另取一個名字句狼,使用對象形式:

mapGetters({
  // 映射 this.double 為 store.getters.countDouble
  double: 'countDouble'
})

mutations

提交mutation是更改Vuex中的store中的狀態(tài)的唯一方法筹吐。

mutation必須是同步的邦危,如果要異步需要使用action陵且。

每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調(diào)函數(shù) (handler)获洲。這個回調(diào)函數(shù)就是我們實際進行狀態(tài)更改的地方,并且它會接受 state 作為第一個參數(shù),提交載荷作為第二個參數(shù)叶沛。(提交荷載在大多數(shù)情況下應(yīng)該是一個對象),提交荷載也可以省略的。

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    //無提交荷載
    increment(state) {
        state.count++
    }
    //提交荷載
    incrementN(state, obj) {
      state.count += obj.n
    }
  }
})

你不能直接調(diào)用一個 mutation handler抗楔。這個選項更像是事件注冊:“當觸發(fā)一個類型為 increment 的 mutation 時卢肃,調(diào)用此函數(shù)』淝龋”要喚醒一個 mutation handler跨跨,你需要以相應(yīng)的 type 調(diào)用 store.commit 方法:

//無提交荷載
store.commit('increment')
//提交荷載
store.commit('incrementN', {
    n: 100
    })

對象風(fēng)格的提交方式
我們也可以使用這樣包含 type 屬性的對象的提交方式。

store.commit({
  type: 'incrementN',
  n: 10
})

Mutations 需遵守 Vue 的響應(yīng)規(guī)則

  • 最好提前在你的 store 中初始化好所有所需屬性拘悦。
  • 當需要在對象上添加新屬性時组砚,你應(yīng)該
    • 使用 Vue.set(obj, 'newProp', 123), 或者
    • 以新對象替換老對象。例如葡公,利用對象展開運算符我們可以這樣寫state.obj = {...state.obj, newProp: 123 }

mapMutations 輔助函數(shù)
與其他輔助函數(shù)類似,你可以在組件中使用 this.$store.commit(‘xxx’) 提交 mutation麸恍,或者使用 mapMutations 輔助函數(shù)將組件中的 methods 映射為 store.commit 調(diào)用(需要在根節(jié)點注入 store)臂聋。

import { mapMutations } from 'vuex'

export default {
  //..
  methods: {
    ...mapMutations([
      'increment' // 映射 this.increment() 為 this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // 映射 this.add() 為 this.$store.commit('increment')
    })
  }
}

actions

Action 類似于 mutation,不同在于:

  • Action 提交的是 mutation或南,而不是直接變更狀態(tài)孩等。
  • Action 可以包含任意異步操作。
    我們用如下例子來結(jié)束actions:
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      setInterval(function(){
        context.commit('increment')
      }, 1000)
    }
  }
})

注意:Action 函數(shù)接受一個與 store 實例具有相同方法和屬性的 context 對象采够,因此你可以調(diào)用 context.commit 提交一個 mutation肄方,或者通過 context.state 和 context.getters 來獲取 state 和 getters。

其他與mutations類似的地方

Actions 支持同樣的載荷方式和對象方式進行分發(fā):

// 以載荷形式分發(fā)
store.dispatch('incrementN', {
  n: 10
})

// 以對象形式分發(fā)
store.dispatch({
  type: 'incrementN',
  n: 10
})

mapActions輔助函數(shù)

你在組件中使用 this.$store.dispatch('xxx') 分發(fā) action蹬癌,或者使用 mapActions 輔助函數(shù)將組件的 methods 映射為 store.dispatch 調(diào)用(需要先在根節(jié)點注入 store):

import { mapActions } from 'vuex'

export default {
  //..
  methods: {
    ...mapActions([
      'incrementN' //映射 this.incrementN() 為 this.$store.dispatch('incrementN')
    ]),
    ...mapActions({
      add: 'incrementN' //映射 this.add() 為 this.$store.dispatch('incrementN')
    })
  }
}

Modules

使用單一狀態(tài)樹权她,導(dǎo)致應(yīng)用的所有狀態(tài)集中到一個很大的對象虹茶。但是,當應(yīng)用變得很大時隅要,store 對象會變得臃腫不堪蝴罪。

為了解決以上問題,Vuex 允許我們將 store 分割到模塊(module)步清。每個模塊擁有自己的 state要门、mutation、action廓啊、getters欢搜、甚至是嵌套子模塊——從上至下進行類似的分割:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)

模塊的局部狀態(tài)
對于模塊內(nèi)部的 mutation 和 getter,接收的第一個參數(shù)是模塊的局部狀態(tài),對于模塊內(nèi)部的 getter谴轮,根節(jié)點狀態(tài)會作為第三個參數(shù):

const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      // state 模塊的局部狀態(tài)
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    },
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

同樣炒瘟,對于模塊內(nèi)部的 action,context.state 是局部狀態(tài)第步,根節(jié)點的狀態(tài)是 context.rootState:

const moduleA = {
  // ...
  actions: {
    incrementIfOddOnRootSum (context) {
      if ((context.state.count + context.rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疮装,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子粘都,更是在濱河造成了極大的恐慌廓推,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驯杜,死亡現(xiàn)場離奇詭異受啥,居然都是意外死亡,警方通過查閱死者的電腦和手機鸽心,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門滚局,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人顽频,你說我怎么就攤上這事藤肢。” “怎么了糯景?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵嘁圈,是天一觀的道長。 經(jīng)常有香客問我蟀淮,道長最住,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任怠惶,我火速辦了婚禮涨缚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘策治。我一直安慰自己脓魏,他們只是感情好兰吟,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著茂翔,像睡著了一般混蔼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上珊燎,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天惭嚣,我揣著相機與錄音,去河邊找鬼俐末。 笑死料按,一個胖子當著我的面吹牛奄侠,可吹牛的內(nèi)容都是我干的卓箫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼垄潮,長吁一口氣:“原來是場噩夢啊……” “哼烹卒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弯洗,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤旅急,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后牡整,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藐吮,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年逃贝,在試婚紗的時候發(fā)現(xiàn)自己被綠了谣辞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡沐扳,死狀恐怖泥从,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情沪摄,我是刑警寧澤躯嫉,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站杨拐,受9級特大地震影響祈餐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哄陶,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一帆阳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奕筐,春花似錦舱痘、人聲如沸变骡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽塌碌。三九已至,卻和暖如春旬盯,著一層夾襖步出監(jiān)牢的瞬間台妆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工胖翰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留接剩,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓萨咳,卻偏偏與公主長得像懊缺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子培他,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容