vue vuex的state,getter,mustation,action,module


Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

Vuex核心屬性:

vuex中給出了幾個核心名詞,state,getter,mutation,action,module。
我們畫圖說明。

屬性名 描述
state 倉庫,里面存放數據
getter 搬運工小組,有無數個搬運工,只負責從廠房往外搬東西
mutation 操作工小組,有無數個操作工,負責更新貨物,只能同步進行
action 操作工小組,有無數個操作工,負責更新貨物,可以異步進行
module 工廠里的廠區,vuex里面可以有無數個廠區

vuex的使用:

// 下載vuex包 npm install --save vuex
然后我們在src目錄下,創建一個store目錄,在該目錄下創建一個index.js文件。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 數據倉庫
const state = {
  // 定義一個公共屬性,並初始化賦值
  name: '廠長'
}

// 數據的搬運工,我可以在其中定義搬運規則
const getters = {
  getName: function (state) {
    // 在這里定義搬運規則,然后返回
    return state.name + '是我表哥'
  }
}

// mutations操作工,專門用於修改state里的屬性的方法集合,只能同步
const mutations = {
  setName (state, payload) {
    state.name = payload
  }
}

// actions操作工,用於修改state里的屬性的方法集合,可以異步
const actions = {
  setName (context, payload) {
    // 這里進行異步操作,最后還是調用了mutations中的方法
    context.commit('setName', payload)
  }
}

// 導出
export default new Vuex.Store({
  state: state,
  mutations: mutations,
  getters: getters,
  actions: actions
  
  // 如果參數名相同,可以簡寫
  state,
  getters,
  mutations,
  actions
})

注意,注意,注意,這里參數,vuex已經規定好了,只能是state,getters,mutations,actions。

最后,別忘了在main.js入口文件中導入該文件。

import Vue from 'vue'
import App from './App'
import router from './router'

// 在這里導入
import store from './store'
import Vuex from 'vuex'

Vue.use(Vuex)

new Vue({
  el: '#app',
  router,
  // 添加到vue實例
  store,
  components: {
    App
  },
  template: '<App/>'
})

簡單的說明了一下vuex,假設廠長是我表哥,我現在可以指揮這個工廠了。

state應用:

上面說過了,state里存放的是數據,要想獲取數據,有兩種辦法。

第一種:廠長親自來取數據,缺點是不能定義規則。
第二種:廠長叫getter搬運工去取,getter搬運工有定義規則的能力。

既然廠長是我表哥,那么就由我代勞了。

在任何組件中,我們都可以使用以下方式,獲取state中的數據。

this.$store.state.name

// 一般,我們會放在computed里。
computed: {
  showName () {
    return this.$store.state.name
  }
}

以上內容可以發現,廠長可以直接來取數據,但缺點是無法過濾數據。

getter應用:

getter專門用來取數據的,並且我可以在里面定義各種各樣的規則。

舉例說明。

const state = {
  // 定義了一個數組,里面包含員工,和他對應的工資
  data: [{
    name: '牛二',
    salary: 3000
  }, {
    name: '張三',
    salary: 3200
  }, {
    name: '李四',
    salary: 3600
  }, {
    name: '王麻子',
    salary: 3800
  }]
}

假設,廠長現在要給工資3500以下的人漲工資,那么我們就可以通過getter知道,有那些人的工資在3500以下。

const getters = {
  getName: function (state) {
    var people = []
    for (var temp of state.count) {
      if (temp.salary < 3500) {
        people.push(temp)
      }
    }
    return people
  }
}

export default new Vuex.Store({
  state,
  getters
})

在任何組件中,我們都可以使用以下方式,通過getter獲取state中的數據。

this.$store.getters.getName

當然,也可以放在computed里封印起來。

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

這里要注意的是官方給出的說明,如下。
Vuex 允許我們在 store 中定義“getter”(可以認為是 store 的計算屬性)。就像計算屬性一樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變才會被重新計算。

mutation應用:

mutation專門用來更新數據的。
最重要的是:mutation是同步的,同步的,同步的。

官方給出的說明如下。
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個參數。
舉例說明

const state = {
  name: '廠長'
}

const mutations = {
  // 在這里進行更改
  setName (state) {
    state.name += '是我表哥'
  }
}

export default new Vuex.Store({
  state,
  mutations
})

既然mutation被當做事件,那么就不能稱之為調用了,在vuex中,通過以下方式,觸發mutation。

store.commit('setName')
那么,也就是說,在任何組件里,都可以通過如下方式,使用mutation,一般將mutation封印在methods中。

this.$store.commit('xxx')

以上例子中,name的變更方式已經被固定死了,我希望按照我制定的方式變更。
vuex中有如下說明。
你可以向 store.commit 傳入額外的參數,即 mutation 的 載荷(payload)
舉例說明

const state = {
  name: '廠長'
}

const mutations = {
  // 接收一個str參數,即mutation的載荷
  setName (state, str) {
    state.name += str
  }
}

export default new Vuex.Store({
  state,
  mutations
})

觸發方式不變,也就是多了個參數。

store.commit('setName', '是我表哥')

action應用:

action和mutation同樣是操作工,但是action還是要牛一些的。
action牛的地方在於,有些活兒他不干,他讓mutation去干。
最重要的是,action可以異步,可以異步,可以異步。

官方有如下說明。

Action 提交的是 mutation,而不是直接變更狀態。
Action 可以包含任意異步操作。```

比如,我現在讓action去干活,他覺得活兒太簡單了,就讓action去干,結果就是他睡一覺起來,活兒干完了。

舉例說明。

const actions = {
setName (context, name) {
// action自己去睡了一覺,讓mutation去干活
setTimeout(() => {
context.commit('setName', name)
}, 5000)
}
}

action的調用,稱之為分發,在vuex中,通過以下方式,分發action。

`store.dispatch('setName', name)
`
在任何組件里,都可以通過如下方式,使用action,一般將action封印在methods中。

`this.$store.dispatch('xxx')
`
這里要注意的是:
Action 函數接受一個與 store 實例具有相同方法和屬性的 context 對象,我們可以通過這個 context 對象獲取當前 store 實例的 state 和 getters,但是這個 context 對象,不是 store 實例本身,不是,不是,不是。
上圖說明
##### context 對象
![](https://img2018.cnblogs.com/blog/1545354/201903/1545354-20190313164119686-1188430760.png)

##### store 實例

![](https://img2018.cnblogs.com/blog/1545354/201903/1545354-20190313164206101-110479817.png)

只是有點像,但是二者不一樣。

#### module應用:
module的作用就是將state,getter,mutation,action拆分,這樣就避免了所有代碼混在一起的情況。

舉例說明。

const moduleA = {
state: {
name: '模塊A'
},
mutations: {},
actions: {},
getters: {}
}

const moduleB = {
state: {
name: '模塊B'
},
mutations: {},
actions: {},
getters: {}
}

export default new Vuex.Store({
state: {
name: '根節點'
},
mutations: {},
actions: {},
getters: {},
modules: {
a: moduleA,
b: moduleB
}
})

這里要注意的是,模塊內部的 mutation 和 getter,接收的第一個參數是模塊的局部狀態對象。
也就是說,模塊內部的mutation和getter,用的是自己的倉庫。
而action接收的還是一個和store實例相似的對象。
舉例說明

const moduleA = {
namespaced: true,
state: {
name: '模塊A'
},
mutations: {
myMutation: function (
// 如果在模塊中定義則為模塊的局部狀態
state,
// 載荷,可選
payload) {

}

},
actions: {
myAction: function (
// context對象
{
state,
rootState,
commit,
dispatch,
getters,
rootGetters
},
// 載荷,可選
payload) {

}

},
getters: {
myGetter: function (
// 如果在模塊中定義則為模塊的局部狀態
state,
// 等同於 store.getters
getters,
// 等同於 store.state
rootState,
// 所有 getters
rootGetters) {
return state.data
}
}
}

即使是分了模塊,state,getter,mustation,action的使用方法還是一樣。

// 使用state
this.\(store.state.name // 使用getter this.\)store.getters.myGetter
// 使用mutation
this.\(store.commit('myMutation', '哈哈哈') // 使用action this.\)store.dispatch('myAction', '哈哈哈')


那么問題來了,如果模塊A和模塊B中的屬性和方法重名,怎么辦?

舉例說明。

const moduleA = {
state: {
name: '模塊A'
},
mutations: {
aaa: function (state) {}
},
actions: {
bbb: function (context) {}
},
getters: {
ccc: function (state) {}
}
}

const moduleB = {
state: {
name: '模塊B'
},
mutations: {
aaa: function (state) {}
},
actions: {
bbb: function (context) {}
},
getters: {
ccc: function (state) {}
}
}

使用命名空間
舉例說明。

const moduleA = {
namespaced: true,
state: {
name: '模塊A'
}
}

const moduleB = {
namespaced: true,
state: {
name: '模塊B'
}
}

export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})


在上述例子中,我加了一個屬性`namespaced: true`,表示使用命名空間,那么在使用state,getter,mustation,action時,就得加上命名空間。

// 使用state
this.\(store.state.a.name // 使用getter this.\)store.getters['a/myGetter']
// 使用mutation
this.\(store.commit('a/myMutation', '哈哈哈') // 使用action this.\)store.dispatch('a/myAction', '哈哈哈')


還有就是,module還可以嵌套,不過基本上都是大同小異


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM