Vuex詳解

Vuex是做什么的乌妒?

  1. 官方解釋:Vuex是一個專為Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式。
  • 它采用集中式存儲管理應(yīng)用的所有組件狀態(tài)涌庭,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化芥被。
  • Vuex也集成到Vue的官方調(diào)試工具devtools extension欧宜,提供了諸如零配置的time-travel調(diào)試坐榆、狀態(tài)快照導(dǎo)入導(dǎo)出等高級調(diào)試功能。

2. 狀態(tài)管理到底是什么?

  • 狀態(tài)管理模式冗茸、集中式存儲管理這些名詞聽起來就非常高大上席镀,讓人捉摸不透。
  • 其實夏漱,你可以簡單的將其看成把需要多個組件共享的變量全部存儲在一個對象里面豪诲。
  • 然后,將這個對象放在頂層的Vue實例中挂绰,讓其他組件可以使用屎篱。
  • 那么,多個組件是不是就可以共享這個對象中的所有變量屬性了呢葵蒂?

Vuex狀態(tài)管理圖例

簡單的案例

實現(xiàn)一個簡單的加減案例

  • 首先交播,我們需要在某個地方存放我們的Vuex代碼:
    1. 這里,我們先創(chuàng)建一個文件夾store践付,并且在其中創(chuàng)建一個index.js文件
    2. 在index.js文件中寫入如下代碼:
     import Vue from 'vue'
     import Vuex from 'vuex'
    
     Vue.use(Vuex)
    
     export default new Vuex.Store({
       state: {
       count:0
     },
     mutations: {
       //方法
       increment(state){
         state.count++
       }
       decrement(state){
         state.count--
       }
     },
    })
    
  • 其次秦士,我們讓所有的Vue組件都可以使用這個store對象
    1. 來到main.js文件,導(dǎo)入store對象永高,并且放在new Vue中
    2. 這樣隧土,在其他Vue組件中,我們就可以通過this.$store的方式命爬,獲取到這個store對象了
     import Vue from 'vue'
     import App from './App.vue'
     import store from './store'
    
     new Vue({
       store,
       render: h => h(App)
     }).$mount('#app')
    
  • 使用Vuex的count
     <template>
       <div>
         <p>{{count}}</p>
         <button @click="increment">+1</button>
         <button @click="decrement">-1</button>
       </div>
     </template>
     <script>
       export default {
         name: 'App',
         computed: {
           count: function () {
             return this.$store.state.count
           }
         },
         methods: {
           increment: function() {
             this.$store.commit('increment')
           }
           decrement: function() {
             this.$store.commit('decrement')
           }
         }
       }
     </script>
    

以上曹傀,就是使用Vuex最簡單的方式了
對以上使用步驟做一個簡單的總結(jié):

  • 提取出一個公共的store對象,用于保存在多個組件中共享的狀態(tài)
  • 將store對象放置在new Vue對象中饲宛,這樣可以保證在所有的組件中都可以使用到
  • 在其他組件中使用store對象中保存的狀態(tài)即可
    通過this.$store.state.屬性的方式來訪問狀態(tài)
    通過this.$store.commit('mutation中的方法')來修改狀態(tài)
  • 注意事項:
    1. 我們通過提交mutation的方式卖毁,而非直接改變store.state.count。
    2. 這是因為Vuex可以更明確的追蹤狀態(tài)的變化落萎,所以不要直接改變store.state.count的值亥啦。
    3. 同步操作可以直接通過mutations來修改,但異步不行练链,得先通過Actions

Getters基本使用

  • 有時候翔脱,我們需要從store中獲取一些state變異后的狀態(tài),比如下面的Store中:
    獲取學(xué)生年齡大于20的學(xué)生媒鼓。
       const store = new Vue.store({
         state: {
           students: [
             {id:1, name: 'kk', age: 21},
             {id:2, name: 'hh', age: 19},
           ]
         }
       })
    
  • 我們可以在Store中定義getters
      getters: {
         more20Ages(state) {
           return state.students.filter(s => s.age >=20)
         }
      }
    
  • Getters作為參數(shù)和傳遞參數(shù)
    1. 如果我們已經(jīng)有了一個獲取所有年齡大于20歲學(xué)生列表的getters届吁,那么代碼可以這樣寫
     getters: {
         more20Ages(state) {
           return state.students.filter(s => s.age >=20)
         },
         more20AgesLength(state,getters) {
           return getters.more20Ages.length
         },  
      }
    
    1. getters默認(rèn)是不能傳遞參數(shù)的错妖,如果希望傳遞參數(shù),那么只能讓getters本身返回另一個函數(shù)疚沐。
      //比如我們是希望根據(jù)年齡來獲取用戶信息
      getters: {
        moreAgeStu(state) {
          return age => {
            return state.students.filter(s => s.age > age)
          }
        }
      }
    

Mutation狀態(tài)更新

  • Vuex的store狀態(tài)的更新唯一方式:提交Mutation
  • Mutation主要包括兩部分
    1. 字符串的事件類型(type)
    2. 一個回調(diào)函數(shù)(handler)暂氯,該回調(diào)函數(shù)的第一個參數(shù)就是state。
  • mutations的定義方式:
  mutations: {
    increment(state) {
      state.count++
    }
  }
  • 通過mutation更新
  increment: function () {
    this.$store.commit('increment')
  }

Mutation傳遞參數(shù)

  • 在通過mutation更新數(shù)據(jù)的時候亮蛔,有可能我們希望攜帶一些額外的參數(shù)
    參數(shù)被稱為是mutation的載荷(Payload)
  • Mutation中的代碼
 decrement(state,n) {
   state.count -= n
 }
 decrement: function (count) {
   //payload:負(fù)載
   //普通的的提交封裝
   this.$store.commit('decrement',count)
 }
  • 但如果參數(shù)不是一個呢痴施?
    比如我們有很多參數(shù)需要傳遞
    這個時候,我們通常會以對象的形式傳遞究流,也就是payload是一個對象
    這個時候可以再從對象中取出相關(guān)的信息
 changeCount(state,payload) {
   state.count = payload.count
 }
 changeCount: function () {
   this.$store.commit('changeCount',{count: 0})
 }

Mutation提交風(fēng)格

  • 上面的通過commit進(jìn)行提交是一種普通的方式
  • Vue還提供了另外一種風(fēng)格辣吃,它是一個包含type屬性的對象
 this.$store.commit({
   type: 'changeCount',
     count
 })
  • Mutation中的處理方式是將整個commit的對象作為payload使用,所以代碼沒有改變芬探,依然如下:
 changeCount(state,payload) {
   state.count = payload.count
 }

Mutation響應(yīng)規(guī)則

  • Vuex的store中的state是響應(yīng)式的神得,當(dāng)state中的數(shù)據(jù)發(fā)生改變時,Vue組件會自動更新
  • 這就要求我們必須遵守一些Vuex對應(yīng)的規(guī)則:
    1. 提前在store中初始化好所需的屬性
    2. 當(dāng)給state的對象添加新屬性時偷仿,使用下面的方式:
      方式一:使用Vue.set(obj,'newProp',123) Vue.set(state.info,'address','泉州')
      方式二:用新對象給舊對象重新賦值

Mutation常量類型 - 概念

  • 在用mutation時會有以下問題
    1. 在mutation中哩簿,我們定義了很多事件類型(也就是其中的方法名稱)
    2. 當(dāng)我們的項目增大時,Vuex管理的狀態(tài)越來越多酝静,需要更新狀態(tài)的情況也越來也多节榜,那么意味著Mutation中的方法越來越多
    3. 方法過多,使用者需要花費大量的經(jīng)歷去記住這些方法形入,甚至是多個文件來回切換全跨,查看方法名稱,甚至如果不是復(fù)制的時候亿遂,可能還會出現(xiàn)寫錯的情況浓若。
  • 改進(jìn)措施
    1. 在store下新建一個mutation-types.js文件
      export const INCREMENT = 'increment'
    2. 在提交方法地方導(dǎo)入mutation-types.js這個文件
      import {INCREMENT} from './store/mutation-types.js'
      提交方法就可以改成以下方式
      addition() { this.$store.commit(INCREMENT) }
    3. store.jsmutation方法也需要先導(dǎo)入mutation-types.js
      import {INCREMENT} from './store/mutation-types.js'
      mutation方法就可以改成以下方式
      [INCREMENT](state) { state.counter++ }

Mutation同步函數(shù)

  • 通常情況下,Vuex要求我們Mutation中方法必須是同步方法
    1. 主要原因是當(dāng)我們使用devtools時蛇数,devtools可以幫助我們捕捉mutation的快照
    2. 但如果是異步操作挪钓,那么devtools將不能很好的追蹤這個操作什么時候會被完成

Action的基本定義

  • 當(dāng)我們需要在Vuex中進(jìn)行異步操作,比如網(wǎng)絡(luò)請求耳舅,這時就可以用Action碌上,它是用來代替Mutation進(jìn)行異步操作
  mutations: {
    updateInfo(state) {
      state.info.name = 'kk'
    }
  }
  actions: {
    //context上下文,這里就當(dāng)做store對象
    /**aUpdateInfo(context,payload) {
      setTimeout( () => {
        context.commit('updateInfo')
        console.log(payload.message)  //我是攜帶的信息
        payload.success() //里面異步操作已經(jīng)完成
      },1000)
    }**/
    //可以優(yōu)化返回一個promise
    aUpdateInfo(context,payload) {
      return new promise( (resolve,reject) => {
        setTimeout( () => {
        context.commit('updateInfo')
        console.log(payload)  //我是攜帶的信息
        resolve('kkkkk')
      },1000)
      })
    }
  }
  updateInfo() {
     /**this.$store.dispatch('aUpdateInfo',{
      message: '我是攜帶的信息',
      success: () => {
        console.log('里面異步操作已經(jīng)完成')
      }
     })**/
     //上述代碼還可以優(yōu)化成以下
      this.$store.dispatch('aUpdateInfo','我是攜帶的信息').then(res => {
        console.log('里面完成了提交')
        console.log(res) //kkkkk
      })
      
  }

認(rèn)識Module

  • Module是模塊的意思浦徊,為什么在Vuex中我們要使用模塊呢馏予?
    1. Vue使用單一狀態(tài)數(shù),那么也意味著很多狀態(tài)都會交給Vuex來管理
    2. 當(dāng)應(yīng)用邊得非常復(fù)雜時盔性,store對象就有可能變得相當(dāng)臃腫
    3. 為了解決這個問題霞丧,Vuex允許我們將store分割成模塊(Module),而每個模塊擁有自己的state冕香、mutations蛹尝、actions后豫、getters等
  const moduleA = {
    state: { name: 'kk' },
    mutations: {},
    actions: {},
    getters: {}
  }
  const moduleB = {
    state: {},
    mutations: {},
    actions: {},
    getters: {}
  }
  const store = new Vuex.Store({
    modules: {
      a:moduleA,
      b:moduleB
    }
  })
  store.state.a.name //  ->kk
  store.state.b //  ->moduleB的狀態(tài)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市突那,隨后出現(xiàn)的幾起案子挫酿,更是在濱河造成了極大的恐慌,老刑警劉巖愕难,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件早龟,死亡現(xiàn)場離奇詭異,居然都是意外死亡务漩,警方通過查閱死者的電腦和手機拄衰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門它褪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來饵骨,“玉大人,你說我怎么就攤上這事茫打【哟ィ” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵老赤,是天一觀的道長轮洋。 經(jīng)常有香客問我,道長抬旺,這世上最難降的妖魔是什么弊予? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮开财,結(jié)果婚禮上汉柒,老公的妹妹穿的比我還像新娘。我一直安慰自己责鳍,他們只是感情好碾褂,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著历葛,像睡著了一般正塌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恤溶,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天乓诽,我揣著相機與錄音,去河邊找鬼咒程。 笑死鸠天,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的孵坚。 我是一名探鬼主播粮宛,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼窥淆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了巍杈?” 一聲冷哼從身側(cè)響起忧饭,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎筷畦,沒想到半個月后词裤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡鳖宾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年吼砂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼎文。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡渔肩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拇惋,到底是詐尸還是另有隱情周偎,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布撑帖,位于F島的核電站蓉坎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胡嘿。R本人自食惡果不足惜蛉艾,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衷敌。 院中可真熱鬧勿侯,春花似錦、人聲如沸逢享。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞒爬。三九已至弓柱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間侧但,已是汗流浹背矢空。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留禀横,地道東北人屁药。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像柏锄,于是被迫代替她去往敵國和親酿箭。 傳聞我的和親對象是個殘疾皇子复亏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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

  • Vuex是做什么的? 官方解釋:Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用 集中式存儲...
    獨調(diào)1997閱讀 904評論 0 0
  • 在vue中我們通過vuex來管理狀態(tài)缭嫡,該值一但被修改缔御,所有引用該值的地方都會自動更新項目的src文件下的store...
    我愛阿桑閱讀 258評論 0 2
  • 為什么使用vuex 在中大型應(yīng)用中,應(yīng)用的各個組件間需要進(jìn)行數(shù)據(jù)傳遞妇蛀,使用傳統(tǒng)方式繁瑣且不可控 Vuex 為所有組...
    _cxrs_閱讀 630評論 0 0
  • Vuex是什么 狀態(tài)管理模式耕突,將所有組件需要共享的變量全部存儲在一個對象里,然后將這個對象放在頂層組件中供其他組件...
    前端小兵閱讀 1,386評論 0 3
  • 轉(zhuǎn)載自:https://segmentfault.com/a/1190000015782272 作者:飛躍 ...
    天字一等閱讀 733評論 3 6