Vue中的狀態管理器 - Vuex


我們知道vue是組件式開發的,當你的項目越來越大后,每個組件背后的數據也會變得越來越難以理順,

這個時候你就可以考慮使用vuex了。

備注: 官方建議小項目不要使用,引入vuex會帶來新的概念和模式,這對於新手而言理解上本身有難度,而且小項目中vuex發揮的功效確實不怎么明顯,

反而增加了開發難度,就像后端項目中常說的 過度設計。

說了這么多,下面介入正題(以下講解需要一個空的vue項目,推薦使用 vue-cli 創建,快速搭建一個vue開發環境 ):

vuex的作用就是作為一個數據倉庫(store),把多個組件的背后的數據都放到store中,然后所有組件通過約定的方式去讀取數據和修改數據。

這一句話就概括完了。沒有想象的那么復雜。注意,這句話里面一個關鍵詞叫 約定,下面來說說有那些約定:

在將約定之前,首先還是要知道怎么定義一個倉庫(store),進入項目然后  vue add vuex 。

通過這條命令,vue-cli 幫我們創建了一個 store.js 的文件,並自動在根組件中引入了store,具體變化如下:

main.js 文件中自動變化了兩處

import Vue from 'vue'
import App from './App.vue'    
import store from './store' #【引入store文件】

Vue.config.productionTip = false

new Vue({
  store, #【在根組件中引入了store】
  render: h => h(App)
}).$mount('#app')

現在我們編輯一下 store.js 文件:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
      user: {
        name: '張三', sex: '男'
      }
  },
  mutations: {
    change_name (state,payload) {
      state.user.name = payload.new_name
    },
    change_sex (state,payload) {
      state.user.sex = payload.new_sex
    }
  },
  actions: {
    change_sex_by_action (context,payload) {
      setTimeout(() => {
        context.commit('change_sex',payload)
      },3000)
    }
  }
})

理解:

  state 是狀態(數據中心)。

  mutations 里面定義的函數用來修改state,mutation只能執行同步操作。

  actions 的目的也是更改state,但是他不像mutation一樣可以直接更改state,而是通過調用mutation來更改state。還有一個不同點是,action可以執行異步操作,比如網絡請求。

  getters 返回組裝DIY后的數據,比如state有個sex=“女”,通過getter在后面加一個 生 ,返回 女生,但是我覺得把組件中 computed 干的事情放到store層不是一個好主意,所以本例中不涉及。

用法:

  mutation的一個參數是 state,第二個參數是從 組件傳過來的參數對象,

  action的第一個參數是一個與 store 實例具有相同方法和屬性的 context 對象,這句話有點難以理解,你就把context想象成一個新的store對象,

  第二個參數還是 組件傳過來的參數對象

在編輯一下 App.vue 文件

<template>
  <div id="app">
    <button @click="change_name">change name by mutation</button>
    <p>current name({{ user.name }})</p>
    <button @click="change_sex">change sex by action</button>
    <p>current sex({{ user.sex }})</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      // user: this.$store.state.user
    }
  },
  computed: {
    user() {
      return this.$store.state.user
    }
  },
  methods: {
    change_name() {
      this.$store.commit({
        type: 'change_name',
        new_name: '李四'
      })
    },
    change_sex() {
      this.$store.dispatch({
        type: 'change_sex_by_action',
        new_sex: '女'
      })
    }
  }
}
</script>

 通過store獲取數據都要放到computed里面,雖然在其他地方也可以直接獲取,但是無法監聽數據變動(就像上面注釋的一樣)。

change_name是通過mutation方式同步更改store中的數據,change_sex采用了action方式異步更改store中的數據。

如果在computed中需要獲取的數據很多,可以使用 官方提供的 mapState,具體用法查看官方 文檔 。

我自己的理解:

不要濫用store,不要把所有的數據都放到store中,在組件化開發思想下,我認為組件和組件之間本就應該獨立封裝,

如果一個數據只有在某個組件中使用,而不需要被其他組件共享,那么最好不要放到其中,store只存儲有必要的數據,不要讓他變得太臃腫,否則麻煩遲早會來。

官方文檔中說明,如果store太大可以采用模塊方式分割,但貌似不太優雅,

最后我還是推薦store只放必要的東西,不要讓他變得太肥胖。

 


免責聲明!

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



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