Vuex如何實現數據共享

前言

在用vue做爲前端框架進行開發的時候,對於組件間的傳值你必定不會陌生,若是隻是簡單的父子組件傳值,我想你確定不會選擇用Vuex來進行狀態管理,可是若是你須要構建一箇中大型單頁應用,組件間數據交互比較複雜頻繁,你極可能會考慮如何更好地在組件外部管理狀態,那麼Vuex 將會成爲天然而然的選擇。前端

Vuex 是什麼?

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 這是官方的一種說法。vue

用我的的話總結下:Vuex就是爲了實現多組件數據共享,從而創建一個叫store的數據管理庫,將須要共享的數據存放在裏面,在須要的地方能夠取出來做爲初始數據,也能夠在組件內經過dispatch或者提交commit方法來改變該原始數據狀態,從而實現的data的共享。vuex

Vuex的核心

一、 State

Vuex中的數據源,咱們須要保存的數據就保存在這裏,能夠在頁面經過this.$store.state來獲取咱們定義的數據。redux

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const state = {
  number: 0
}

export default new Vuex.Store({
  state,
});
複製代碼

在頁面中經過this.$store.state.number 便可獲取到當前的值。數組

二、Getter

Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。promise

Getter 接受 state 做爲其第一個參數:緩存

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const state = {
  number: 0
}

const getters = {
  getNumber(state) {
     return state.number + 1
  }
}
export default new Vuex.Store({
  state,
  getters,
});
複製代碼

在頁面你能夠用兩種方式取到getters裏面的值bash

一、經過屬性訪問

Getter 會暴露爲 store.getters 對象,你能夠以屬性的形式訪問這些值 如: this.$store.getters.getNumber前端框架

Getter 也能夠接受其餘 getter 做爲第二個參數:框架

const state = {
  number: 1
}

const getters = {
  getNumber(state) {
     return state.number + 1  // 2
  },
  getDoubNUmber(state, getters) {
     return state.number + getters.getNumber   // 3
  }
}
複製代碼

注意: getter 在經過屬性訪問時是做爲 Vue 的響應式系統的一部分緩存其中的。

二、 經過方法訪問

你也能夠經過讓 getter 返回一個函數,來實現給 getter 傳參。在你對 store 裏的數組進行查詢時很是有用。

const state = {
  number: 1,
  list: [1, 2, 3, 4, 5]
}

const getters = {
  getNumber(state) {
     return state.number + 1  // 2
  },
  getDoubNumber(state, getters) {
     return state.number + getters.getNumber   // 3
  },
  filterNumber:(state)=>(num)=> {
     return state.list.find(item=> item%num === 0)
  }  
}
export default new Vuex.Store({
  state,
  getters,
});
複製代碼

注意,getter 在經過方法訪問時,每次都會去進行調用,而不會緩存結果 this.$store.getters.filterNumber(3)

三、Mutation

更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數, 提交載荷(payload) 做爲額外的參數,而且在大多數狀況下,載荷應該是一個對象,這樣能夠包含多個字段而且使記錄的 mutation 會更易讀:

你能夠這樣寫:

const mutations = {
  increment(state, n) {
    state.number += n
  }
}
複製代碼

但你不能直接調用一個 mutation handler。這個選項更像是事件註冊:「當觸發一個類型爲 increment 的 mutation 時,調用此函數。」要喚醒一個 mutation handler,你須要以相應的 type 調用 store.commit 方法:

this.$store.commit('increment', 1)
複製代碼

也能夠這樣寫:

const mutations = {
  increment(state, payload) {
    state.number += payload.count
  }
}
複製代碼

而後:

使用 this.$store.commit('increment', {count: 1})  提交,
// 或者另外一種方式是直接使用包含 type 屬性的對象進行提交:
this.$store.commit({
    type: 'increment',
    count: 1
})
複製代碼

特別說明:在 Vuex 中,mutation 都是同步任務: 爲了處理異步操做,讓咱們來看一看 Action。

四、 Action

Action 相似於 mutation,不一樣在於:

一、Action 提交的是 mutation,而不是直接變動狀態。

二、Action 能夠包含任意異步操做。

雖然在頁面中經過提交commit是能夠達到修改store中狀態值的目的,可是官方並不建議咱們這樣作,而是讓咱們去提交一個action,在action中提交mutation再去修改狀態值。

const mutations = {
  increment(state) {
    state.number += 1
  }
}
const actions = {
    addNumber(context){
      context.commit('increment')
    }
}
複製代碼

Action 函數接受一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用 context.commit 提交一個 mutation,或者經過 context.state 和 context.getters 來獲取 state 和 getters

addNumber( {commit} ){
    commit('increment')
}
以上這種寫法等同於:
addNumber(context){
    context.commit('increment')
}
複製代碼

Action 經過 store.dispatch 方法觸發:

this.$store.dispatch('addNumber')
複製代碼

同mutation 同樣你也能夠在action的時候傳遞參數

const mutations = {
  increment(state, number) {
    state.number += number
  }
}
const actions = {
    addNumber(context, number){
      context.commit('increment', number)
    }
    或者:
    addNumber( {commit}, number){
      commit('increment', number)
    }
}

觸發方法: this.$store.dispatch('addNumber', 10)
複製代碼

關於在action 處理異步操做能夠看下面這個例子:

const actions = {
    getData({commit}) {
      return new Promise((resolve, reject)=> {
         setTimeout(()=>{
           commit('getList')
           resolve()
         }, 1000)
      })
    }
}
複製代碼

而後再

this.$store.dispatch('getData').then(() => {
   // ...
})
複製代碼

完整 實例:

import Vue from "vue";
import Vuex from "vuex";
import { resolve, reject } from "any-promise";

Vue.use(Vuex);

const state = {
  number: 1,
  list: [1, 2, 3, 4, 5]
}

const getters = {
  getNumber(state) {
     return state.number + 1  // 2
  },
  getDoubNumber(state, getters) {
     return state.number + getters.getNumber   // 3
  },
  filterNumber:(state)=>(num)=> {
     return state.list.find(item=> item%num === 0)
  } 
}

const mutations = {
  increment(state, n) {
    state.number += n
  },
  getList(state) {
    state.list = state.list.forEach((item)=> item*2)
  }
}
const actions = {
    addNumber( {commit} , n){
      commit('increment', n)
    },
    getData({commit}) {
      return new Promise((resolve, reject)=> {
         setTimeout(()=>{
           commit('getList')
           resolve()
         }, 1000)
      })
    }
}

export default new Vuex.Store({
  state,
  getters,
  mutations,
  actions
});
複製代碼

關於 Vuex中mapState、mapGetters、mapMutations、mapActions的用法

要用 首先得引入:

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
複製代碼

這玩意兒其實就是Vuex 內置的輔助函數,方便咱們獲取store裏面的數據和方法

computed: {
  ...mapState([
    'number'
  ])
}
複製代碼
// 使用對象展開運算符將 getter 混入 computed 對象中
computed: {
    ...mapGetters([
      'getNumber',
      'getDoubNumber',
      // ...
    ])
}    
複製代碼
methods: {
    ...mapMutations([
      'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`

    ...mapMutations({
      add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
    })
}    

複製代碼
methods: {
    ...mapActions([
      'addNumber', // 將 `this.addNumber()` 映射爲 `this.$store.dispatch('addNumber')`

      // `mapActions` 也支持載荷:
      'addNumber' // 將 `this.addNumber(amount)` 映射爲 `this.$store.dispatch('addNumber', amount)`
    ]),
    ...mapActions({
      requestData: 'getData' // 將 `this.requestData()` 映射爲 `this.$store.dispatch('getData')`
    })
  }

複製代碼

以上是對Vuex實現狀態管理的一個整個過程的理解,參考官方文檔,而後本身寫一遍,比較容易明白其中的道理,後面有時間想寫React裏面關於Redux實現狀態管理的一個過程,對比其中,其實他們思想差很少, 只不過redux實現過程更多點,敬請期待!

相關文章
相關標籤/搜索