【Vue】多組件數據共享Vuex及Vuex 模塊化

多組件數據共享: Vuex

我們知道每一個組件都有自己的 data,那麼多個組件如何共享數據?這就引出了 state 的概念,可以把多個組件共有的屬性統一由state進行管理。但是組件並不能直接訪問或操作state裏的數據源,而是通過 mutations 來對數據源進行操作。而改變數據的行爲觸發由 Actions 來完成,Vue 爲 actions的觸發提供了一個 commit 的概念,由action 觸發通過 mutations 對數據進行操作,從而改變 state 數據源。

那麼 vue 的組件(components)如何操作 state 數據源呢?components 通過鼠標、鍵盤等交互行爲觸發 (Dispatch) Vuex 的Actions,Actions 對操作進行提交,找到對應的 mutations,進而對 state進行改變。這就是 Vuex 的完整數據流。上代碼:

首先,安裝 vuex

npm i vuex

新建 store.js

touch src/store.js

Vue中可以存放數據的有組件的 data、computed、props,而state就是放在 computed裏。

// store.js

import Vue from 'vue' //引入 vue
import Vuex from 'vuex' // 引入vuex
Vue.use(Vuex) // 將Vue 的全局組件 Vuex 加入到 Vue 的運行框架中

const state = { //數據源
  count: 1
}
const mutations = { //定義數據操作方法
  increment(state) { // 傳入數據源
    state.count++ // 操作數據源
  },
  decrement(state) { // 同上
    state.count--
  }
}

// actions 不能直接修改數據, 它會接收 vue 組件的用戶行爲,進一步觸發(commit)操作,由mutations 對數據源state進行修改。補充說明:commit 攜帶一個參數,這個參數就是 mutations 裏的某一個行爲,這個行爲會對數據源state進行操作,並使vue組件重新render數據變化

const actions = { // 定義數據源操作行爲
  increment: ({
    commit
  }) => { // 解構賦值
    commit('increment') // 對應 mutations裏的increment,告訴mutations 進行increment 操作
  },
  decrement: ({
    commit
  }) => { // 解構賦值
    commit('decrement') // 對應 mutations裏的decrement,告訴mutations 進行decrement 操作
  }
}

// 導出 vuex 的實例
export default new Vuex.Store({
  state,
  mutations,
  actions
})

項目入口文件:

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

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store 
// 通過在根實例中註冊 store 選項,把 store 對象提供給 “store” 選項,這可以把 store 的實例注入所有的子組件,子組件可以通過 this.$store 訪問
}).$mount('#app')

vue組件(component):

在組件中分發 Actions:

在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用 mapActions 輔助函數將組件的 methods 映射爲 store.dispatch 調用(需要先在根節點注入 store):

// vuex.vue
<template>
  <div class="vuex">
    vuex {{$store.state.count}}
    <!-- 用 $store 取 store 的state數據源 -->
    <button @click="increment">增加</button>
    <button @click="decrement">刪減</button>
  </div>
</template>
<script>
import { mapActions } from 'vuex'  // 引入 vuex的 actions
export default {
  methods: mapActions([  // 將methods 映射爲 vuex 的 actions
    'increment',
    'decrement'
  ])
}
</script>

延伸:Vuex 模塊化

先創建好模塊目錄及模塊文件

mkdir src/store   // 創建 store 目錄
mkdir src/store/modules   // 創建store 模塊目錄
touch src/store/modules/a.js   // 創建 a 模塊
touch src/store/modules/b.js  // 創建 b 模塊
touch src/store/index.js  // 創建 store 模塊入口文件
touch src/components/a.vue   // 創建子組件a
touch src/components/b.vue   // 創建子組件b
// a.js

const state = {
  money: 10
}

const mutations = {
  add(state) {
    state.money++
  },
  reduce(state) {
    state.money--
  }
}

const actions = {
  add: ({
    commit
  }) => {
    commit('add')
  },
  reduce: ({
    commit
  }) => {
    commit('reduce')
  }
}

export default {
  namespaced: true,  //開啓命名空間
  state,
  mutations,
  actions
}
// b.js

const state = {
  count: 1
}

const mutations = {
  add(state, param) { // mutations 從 actions 上接收 param 參數並且使用
    state.count += param
  },
  reduce(state) {
    state.count--
  }
}

const actions = {
  add: ({
    commit
  }, param) => { // 這裏param參數是從用戶交互action行爲上接收的參數
    commit('add', param)
  },
  reduce: ({
    commit
  }) => {
    commit('reduce')
  }
}

export default {
  namespaced: true,  //開啓命名空間
  state,
  mutations,
  actions
}
// index.js store 入口文件

import Vue from 'vue'    // 引入 vue
import Vuex from 'vuex'   // 引入 vuex
import money from './modules/a'   // 引入模塊a
import count from './modules/b'   // 引入模塊b

Vue.use(Vuex)   // 引入Vue的全局模塊 Vuex

export default new Vuex.Store({
  modules: {   // 導出模塊
    money,   // 子模塊a
    count    // 子模塊b
  }
})
// a.vue

<template>
  <div class="a">
    <!-- 注意:這裏從money模塊下取state數據 money -->
    page a{{$store.state.money.money}}
    <button @click="add">添加</button>
    <button @click="reduce">刪減</button>
  </div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
  methods: mapActions('money', ['add', 'reduce']) 
    // 這裏mapActions 接收兩個參數,第一個參數是store 子模塊名,第二個參數是actions的行爲
}
</script>
// b.vue

<template>
  <div class="b">
    <!-- 注意:這裏從count模塊下取state數據 count-->
    page b{{$store.state.count.count}}
    <!-- 想要mutation 對數據的操作可控,可以在用戶交互的 action上傳參,在b.js 的actions 接收參數 -->
    <button @click="add(2)">添加</button>
    <button @click="reduce">刪減</button>
  </div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
  methods: mapActions('count', ['add', 'reduce'])
    // 這裏mapActions 接收兩個參數,第一個參數是store 子模塊名,第二個參數是actions的行爲
}
</script>
// App.vue

<template>
  <div id="app">
    <!--在dom裏引入組件a和b-->
    <pagea />
    <pageb />
  </div>
</template>

<script>
import pagea from './components/a' // 引入組件a
import pageb from './components/b' // 引入組件b

export default {
  name: 'app',
  components: {
    pagea, // 註冊組件 a
    pageb  //註冊組件 b
  }
}
</script>

 

// 項目主入口文件 main.js

import Vue from 'vue'
import App from './App'
import store from './store/index' // 引入 store 模塊入口文件

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store // 把Vuex的實例引入Vue實例中
}).$mount('#app')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章