Vuex快速入門(mén)

1.vuex是什么

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)喷面,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化偏灿。


vuex核心

上圖中綠色虛線包裹起來(lái)的就是vuex的核心丹诀,state保存的是公共狀態(tài),并只能通過(guò)mutation進(jìn)行更改菩混,而action可以異步的執(zhí)行mutation忿墅。如果你現(xiàn)在還不理解,沒(méi)有關(guān)系沮峡,看完下文的解釋和案例疚脐,相信你會(huì)有更好的理解。

2.為什么要用vuex

現(xiàn)如今的主流狀態(tài)管理器不管Vuex還是Redux都提倡單向數(shù)據(jù)流去管理狀態(tài)邢疙。簡(jiǎn)單的單向數(shù)據(jù)流是指用戶訪問(wèn)View棍弄,View發(fā)出用戶交互的Action,在Action里對(duì)state進(jìn)行相應(yīng)更新疟游。state更新后會(huì)觸發(fā)View更新頁(yè)面的過(guò)程呼畸。這樣數(shù)據(jù)總是清晰的單向進(jìn)行流動(dòng),便于維護(hù)并且可以預(yù)測(cè)颁虐。
一個(gè)簡(jiǎn)單的單向數(shù)據(jù)流模型:

單向數(shù)據(jù)流模型

但是蛮原,當(dāng)我們的應(yīng)用遇到多個(gè)組件共享狀態(tài)時(shí),單向數(shù)據(jù)流的簡(jiǎn)潔性很容易被破壞另绩。

  • 多個(gè)視圖依賴于同一狀態(tài)
  • 來(lái)自不同視圖的行為需要變更同一狀態(tài)

直接看這兩個(gè)問(wèn)題儒陨,你可能不是太懂花嘶,我們換一種方式來(lái)講:
試想:
如果一個(gè)父組件App.vue,下面有2個(gè)子組件:A.vue和B.vue蹦漠。App.vue想要和A.vue和B.vue通信可以使用props傳值的方式椭员。但如果A.vue和B.vue通信就很麻煩,必須通過(guò)App.vue自定義事件來(lái)實(shí)現(xiàn)笛园。
再試想:
如果App.vue下面有很多子組件隘击,這些子組件又依賴于其他組件。這樣的話研铆,父組件App.vue將要監(jiān)聽(tīng)大量的事件埋同,再分發(fā)給不同的子組件,組件之間的通信將會(huì)變得異常繁瑣蚜印。這不會(huì)是我們想要的組件化開(kāi)發(fā)體驗(yàn)莺禁。
好了,vuex就是為了解決這些問(wèn)題而出現(xiàn)的窄赋。

3.引入vuex

  1. 通過(guò)npm下載
    npm install vuex --save
  2. 在main.js里添加
import Vuex from 'vuex'
Vue.use( Vuex );
const store = new Vuex.Store({
    //待添加
})
new Vue({
    el: '#app',
    store,
    render: h => h(App)
})

4.vuex的核心概念

vuex的核心概念有:State哟冬,GettersMutation忆绰,Action浩峡,Module。我們依次來(lái)看:

1.State

state就是Vuex中的公共的狀態(tài), 我們可以把state看作是所有組件的data错敢, 用于保存所有組件的公共數(shù)據(jù)翰灾。此時(shí),我們可以把所有組件公用的數(shù)據(jù)放到state里:

const store = new Vuex.Store({
  state:{ 
    users: [
      {name: '鐘童', age: 18},
      {name: '小明', age: 20},
      {name: '李雷', age: 30},
      {name: '小花', age: 22}
    ]
  }
})

在我們的組件里可以通過(guò)這種方式來(lái)取到state里user的數(shù)據(jù):

export default {
    data () {
        return {
            users : this.$store.state.users //獲取store中state的數(shù)據(jù)
        }
    }
}

2.Getters

Getters我們可以理解為computed屬性稚茅,可以認(rèn)為是store的計(jì)算屬性纸淮。getters的返回值會(huì)根據(jù)它的依賴被緩存起來(lái),且只有當(dāng)它的依賴值發(fā)生了改變才會(huì)被重新計(jì)算亚享。我們現(xiàn)在來(lái)添加一個(gè)getters:

  • 這個(gè)getters的作用是用來(lái)計(jì)算我們的實(shí)際年齡(年齡減半)(不能笑)
// 以下核心概念均添加在store對(duì)象下
getters:{ //添加getters
    realAge: (state) => {
      let realAge = state.users.map( user => {
        return {
          name: user.name,
          age: user.age / 2
        }
      })
      return realAge;
    }
  }

同樣咽块,我們可以通過(guò)這種方式取到getters里realAge計(jì)算后返回的user:

export default {
    data () {
        return {
            users : this.$store.getters.realAge 
        }
    }
}

當(dāng)然,我們也可以使用官方提供的輔助函數(shù)...mapGetters,其實(shí)就是一個(gè)語(yǔ)法糖欺税。代碼如下:

import { mapGetters } from 'vuex'

computed:{
  ...mapGetters(['realAge'])
}

3.Mutation

mutation我們理解為methods屬性侈沪,mutation對(duì)象中保存著更改state狀態(tài)的回調(diào)函數(shù)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方晚凿。第一個(gè)參數(shù)是state 亭罪,第二個(gè)參數(shù)是payload,也就是自定義參數(shù)歼秽,這個(gè)參數(shù)通常在實(shí)際項(xiàng)目中以對(duì)象的形式傳入应役。
現(xiàn)在我們來(lái)添加一個(gè)mutation:

  • 這個(gè)mutation的作用是用來(lái)修飾我們的名字
 // 以下核心概念均添加在store對(duì)象下
  mutations:{ //添加mutations
    psName (state, payload ) {
      let newName = state.users.forEach( user => {
        user.name += payload
      })
    }
  }

然后我們給一個(gè)button注冊(cè)點(diǎn)擊事件:

<template>
    <div>
        <button @click="psName">變有錢</button>
    </div>
</template>

接著再通過(guò)點(diǎn)擊事件調(diào)用mutation:

 psName() {
   this.$store.commit('psName','明天彩票中獎(jiǎng)')
 }

同樣,我們可以使用...mapMutation:

import { mapMutations } from 'vuex'

methods:{
  ...mapMutations(['psName'])
}

4.Action

action類似于mutation,不同在于:

  • action提交的是mutation箩祥,而不是直接變更狀態(tài)
  • action可以包含異步操作呻惕,而mutation只允許同步操作
  • action通過(guò)dispatch來(lái)分發(fā)

action中第一個(gè)參數(shù)是一個(gè)上下文對(duì)象context,類似于canvas里的context滥比,可以取到store實(shí)例下的所有屬性和方法
現(xiàn)在我們來(lái)寫(xiě)一個(gè)action異步執(zhí)行剛才寫(xiě)的mutation:

 // 以下核心概念均添加在store對(duì)象下  
actions:{ //添加actions
    psNameAsync( context, payload ) {
      setTimeout( () => {
        context.commit( 'psName', payload ); //context提交
      }, 2000)
    }
  }

然后我們給一個(gè)button注冊(cè)點(diǎn)擊事件:

<template>
    <div>
        <button @click="psNameAsync">異步變有錢</button>
    </div>
</template>

調(diào)用action:

 psNameAsync() {
   this.$store.dispatch('psNameAsync','明天彩票中獎(jiǎng)啦')
 }

同樣,我們也可以使用...mapActions做院,方法同上盲泛,代碼不再贅述

5.module

由于使用單一狀態(tài)樹(shù),應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象键耕。當(dāng)應(yīng)用變得非常復(fù)雜時(shí)寺滚,store 對(duì)象就有可能變得相當(dāng)臃腫。
為了解決以上問(wèn)題屈雄,Vuex 允許我們將 store 分割成模塊(module)村视。每個(gè)模塊擁有自己的 state、mutation酒奶、action蚁孔、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:

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)

有一點(diǎn)需要注意的是:

默認(rèn)情況下惋嚎,模塊內(nèi)部的 action杠氢、mutation 和 getter 是注冊(cè)在全局命名空間,而state則是注冊(cè)在模塊下的局部空間另伍。因此action鼻百、mutation 和 getter可以直接全局訪問(wèn),而state需要指定某個(gè)module摆尝。

但是:

如果希望你的模塊具有更高的封裝度和復(fù)用性温艇,你可以通過(guò)添加 namespaced: true 的方式使其成為帶命名空間的模塊。當(dāng)模塊被注冊(cè)后堕汞,它的所有 getter勺爱、action 及 mutation 都會(huì)自動(dòng)根據(jù)模塊注冊(cè)的路徑調(diào)整命名。例如:

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模塊內(nèi)容(module assets)
      state: { ... }, // 模塊內(nèi)的狀態(tài)已經(jīng)是嵌套的了臼朗,使用 `namespaced` 屬性不會(huì)對(duì)其產(chǎn)生影響
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模塊
      modules: {
        // 繼承父模塊的命名空間
        myPage: {
          state: { ... },
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 進(jìn)一步嵌套命名空間
        posts: {
          namespaced: true,

          state: { ... },
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

好了邻寿,看到這里你是不是對(duì)Vuex有了更好的理解了呢

【相關(guān)鏈接】

  1. vuex官方文檔:https://vuex.vuejs.org/zh/installation.html
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市视哑,隨后出現(xiàn)的幾起案子绣否,更是在濱河造成了極大的恐慌,老刑警劉巖挡毅,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒜撮,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)段磨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)取逾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人苹支,你說(shuō)我怎么就攤上這事砾隅。” “怎么了债蜜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵晴埂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我寻定,道長(zhǎng)儒洛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任狼速,我火速辦了婚禮琅锻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘向胡。我一直安慰自己恼蓬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布捷枯。 她就那樣靜靜地躺著滚秩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪淮捆。 梳的紋絲不亂的頭發(fā)上郁油,一...
    開(kāi)封第一講書(shū)人閱讀 52,713評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音攀痊,去河邊找鬼桐腌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛苟径,可吹牛的內(nèi)容都是我干的案站。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棘街,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蟆盐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起遭殉,我...
    開(kāi)封第一講書(shū)人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤石挂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后险污,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體痹愚,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡富岳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拯腮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窖式。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖动壤,靈堂內(nèi)的尸體忽然破棺而出萝喘,到底是詐尸還是另有隱情,我是刑警寧澤琼懊,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布蜒灰,位于F島的核電站,受9級(jí)特大地震影響肩碟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凸椿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一削祈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脑漫,春花似錦髓抑、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至网杆,卻和暖如春羹饰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碳却。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工队秩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昼浦。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓馍资,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親关噪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鸟蟹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

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

  • 本文為課程 vuex深入淺出 的學(xué)習(xí)總結(jié)與記錄;同時(shí)參照了vuex官方文檔使兔。文中demo的代碼可參考:我的碼云 一...
    明滅_閱讀 8,750評(píng)論 1 28
  • 安裝 npm npm install vuex --save 在一個(gè)模塊化的打包系統(tǒng)中建钥,您必須顯式地通過(guò)Vue.u...
    蕭玄辭閱讀 2,945評(píng)論 0 7
  • ### store 1. Vue 組件中獲得 Vuex 狀態(tài) ```js //方式一 全局引入單例類 // 創(chuàng)建一...
    蕓豆_6a86閱讀 732評(píng)論 0 3
  • Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)火诸,并以相應(yīng)...
    白水螺絲閱讀 4,672評(píng)論 7 61
  • vuex 場(chǎng)景重現(xiàn):一個(gè)用戶在注冊(cè)頁(yè)面注冊(cè)了手機(jī)號(hào)碼锦针,跳轉(zhuǎn)到登錄頁(yè)面也想拿到這個(gè)手機(jī)號(hào)碼,你可以通過(guò)vue的組件化...
    sunny519111閱讀 8,022評(píng)論 4 111