溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue的Flux框架之Vuex狀態(tài)管理器

發(fā)布時間:2020-09-16 15:51:56 來源:腳本之家 閱讀:186 作者:osjj 欄目:web開發(fā)

學(xué)習(xí)vue之前,最重要是弄懂兩個概念,一是“what”,要理解vuex是什么;二是“why”,要清楚為什么要用vuex。

Vuex是什么?

Vuex 類似 React 里面的 Redux 的狀態(tài)管理器,用來管理Vue的所有組件狀態(tài)。

為什么使用Vuex?

當(dāng)你打算開發(fā)大型單頁應(yīng)用(SPA),會出現(xiàn)多個視圖組件依賴同一個狀態(tài),來自不同視圖的行為需要變更同一個狀態(tài)。
遇到以上情況時候,你就應(yīng)該考慮使用Vuex了,它能把組件的共享狀態(tài)抽取出來,當(dāng)做一個全局單例模式進(jìn)行管理。這樣不管你在何處改變狀態(tài),都會通知使用該狀態(tài)的組件做出相應(yīng)修改。

下面講解如何使用Vuex

一個簡單的Vuex示例

本文就講解安裝Vuex,直接通過代碼講解Vuex使用。

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

上面就是一個簡單的Vuex示例,每一個Vuex應(yīng)用就是一個store,在store中包含組件中的共享狀態(tài)state和改變狀態(tài)的方法(暫且稱作方法)mutations。

需要注意的是只能通過mutations改變store的state的狀態(tài),不能通過store.state.count = 5;直接更改(其實可以更改,不建議這么做,不通過mutations改變state,狀態(tài)不會被同步)。

使用store.commit方法觸發(fā)mutations改變state:

store.commit('increment');

console.log(store.state.count) // 1

一個簡簡單單的Vuex應(yīng)用就實現(xiàn)了。

在Vue組件使用Vuex

如果希望Vuex狀態(tài)更新的時候,組件數(shù)據(jù)得到相應(yīng)的更新,那么可以用計算屬性computed獲取state的更新狀態(tài)。

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count;
    }
  }
}

每一個store.state都是全局狀態(tài),在使用Vuex時候需要在根組件或(入口文件)注入。

// 根組件
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
const app = new Vue({
  el: '#app',
  store,
  components: {
    Counter
  },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

通過這種注入機制,就能在子組件Counter通過this.$store訪問:

// Counter 組件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState函數(shù)

computed: {
  count () {
    return this.$store.state.count
  }
}

上面通過count計算屬性獲取同名state.count屬性,如何每一次獲取都要寫一個這樣的方法,是不顯得重復(fù)又麻煩?可以使用mapState函數(shù)簡化這個過程。

import { mapState } from 'vuex';

export default {
  computed: mapState ({
    count: state => state.count,
    countAlias: 'count',  // 別名 `count` 等價于 state => state.count
  })
}

還有更簡單的使用方法:

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

Getters對象

如果我們需要對state對象進(jìn)行做處理計算,如下:

computed: {
  doneTodosCount () {
    return this.$store.state.todos.filter(todo => todo.done).length
  }
}

如果多個組件都要進(jìn)行這樣的處理,那么就要在多個組件中復(fù)制該函數(shù)。這樣是很沒有效率的事情,當(dāng)這個處理過程更改了,還有在多個組件中進(jìn)行同樣的更改,這就更加不易于維護(hù)。

Vuex中g(shù)etters對象,可以方便我們在store中做集中的處理。Getters接受state作為第一個參數(shù):

const store = new Vuex.Store({
 state: {
  todos: [
   { id: 1, text: '...', done: true },
   { id: 2, text: '...', done: false }
  ]
 },
 getters: {
  doneTodos: state => {
   return state.todos.filter(todo => todo.done)
  }
 }
})

在Vue中通過store.getters對象調(diào)用:

computed: {
 doneTodos () {
  return this.$store.getters.doneTodos
 }
}

Getter也可以接受其他getters作為第二個參數(shù):

getters: {
 doneTodos: state => {
   return state.todos.filter(todo => todo.done)
 },
 doneTodosCount: (state, getters) => {
  return getters.doneTodos.length
 }
}

mapGetters輔助函數(shù)

與mapState類似,都能達(dá)到簡化代碼的效果。mapGetters輔助函數(shù)僅僅是將store中的getters映射到局部計算屬性:

import { mapGetters } from 'vuex'

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

上面也可以寫作:

computed: mapGetters([
   'doneTodosCount',
   'anotherGetter',
   // ...
  ])

所以在Vue的computed計算屬性中會存在兩種輔助函數(shù):

import { mapState, mapGetters } from 'vuex';

export default {
  // ...
  computed: {
    ...mapGetters([ ... ]),
    ...mapState([ ... ])
  }
}

Mutations

之前也說過了,更改Vuex的store中的狀態(tài)的唯一方法就是mutations。

每一個mutation都有一個事件類型type和一個回調(diào)函數(shù)handler。

調(diào)用mutation,需要通過store.commit方法調(diào)用mutation type:

store.commit('increment')

Payload 提交載荷

也可以向store.commit傳入第二參數(shù),也就是mutation的payload:

mutaion: {
  increment (state, n) {
    state.count += n;
  }
}

store.commit('increment', 10);

單單傳入一個n,可能并不能滿足我們的業(yè)務(wù)需要,這時候我們可以選擇傳入一個payload對象:

mutation: {
  increment (state, payload) {
    state.totalPrice += payload.price + payload.count;
  }
}

store.commit({
  type: 'increment',
  price: 10,
  count: 8
})

mapMutations函數(shù)

不例外,mutations也有映射函數(shù)mapMutations,幫助我們簡化代碼,使用mapMutations輔助函數(shù)將組件中的methods映射為store.commit調(diào)用。

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

注 Mutations必須是同步函數(shù)。

如果我們需要異步操作和提交多個Mutations,Mutations就不能滿足我們需求了,這時候我們就需要Actions了。

Actions

Action 類似于 mutation,不同在于:

  1. Action 提交的是 mutation,而不是直接變更狀態(tài)。
  2. Action 可以包含任意異步操作。

讓我們來注冊一個簡單的 action:

var store = new Vuex.Store({
 state: {
  count: 0
 },
 mutations: {
  increment: function(state) {
   state.count++;
  }
 },
 actions: {
  increment: function(store) {
   store.commit('increment');
  }
 }
});

分發(fā) Action

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

分發(fā) Action

Action 通過 store.dispatch 方法觸發(fā):

乍一眼看上去感覺多此一舉,我們直接分發(fā) mutation 豈不更方便?實際上并非如此,還記得 mutation必須同步執(zhí)行這個限制么?Action就不受約束! 我們可以在 action 內(nèi)部執(zhí)行異步操作:

actions: {
 incrementAsync ({ commit }) {
  setTimeout(() => {
   commit('increment')
  }, 1000)
 }
}

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

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

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

mapActions

同樣地,action也有相對應(yīng)的mapActions 輔助函數(shù)

mapActions

mapActions 輔助函數(shù)跟mapMutations一樣都是組件的 methods 調(diào)用:

import { mapActions } from 'vuex'

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

mutation-types

關(guān)于mutation-types方面的講解官方文檔很少說明,但在實際的中大項目中,對==mutation-types==的配置是必不可少的,Vuex的文檔只講解了state,getters,mutation,actions四個核心概念,下面我簡單補充下mutation-types的使用。

顧名思義,==mutation-types==其實就是mutation實例中各個方法的設(shè)定,一般要mutation方法前先在mutation-types用大寫寫法設(shè)定,再在mutation里引入使用,下面看看項目實際使用:

項目組織結(jié)構(gòu)

Vue的Flux框架之Vuex狀態(tài)管理器

在mutation-types定義好mutation的方法結(jié)構(gòu):

//SET_SINGER,SET_SONG 為mutation中要使用的方法名

export const SET_SINGER = 'SET_SINGER'

export const SET_SONG = 'SET_SONG'

在mutation中導(dǎo)入使用:

import * as types from ',/mutation-types.js'

const mutations = {
  [types.SET_SINGER](state, singer) {
    .... 
  },
  [types.SET_SONG](state, song) {
    .... 
  }
}

結(jié)語

看完上面對vuex的講解相信你已經(jīng)入門了,現(xiàn)在可以看看具體的項目加深理解,可以參考我的github一個購物車?yán)? https://github.com/osjj/vue-shopCart

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI