Vue筆記(十六) vuex

vuex 理解

vuex 是什麼

1) github 站點: https://github.com/vuejs/vuex
2) 在線文檔: https://vuex.vuejs.org/zh-cn/
3) 簡單來說: 對 vue 應用中多個組件的共享狀態進行集中式的管理(讀/寫)

狀態自管理應用

1) state: 驅動應用的數據源
2) view: 以聲明方式將 state 映射到視圖
3) actions: 響應在 view 上的用戶輸入導致的狀態變化(包含 n 個更新狀態的方法)

 

多組件共享狀態的問題

1) 多個視圖依賴於同一狀態
2) 來自不同視圖的行爲需要變更同一狀態
3) 以前的解決辦法
a. 將數據以及操作數據的行爲都定義在父組件
b. 將數據以及操作數據的行爲傳遞給需要的各個子組件(有可能需要多級傳遞)
4) vuex 就是用來解決這個問題的

 

vuex 核心概念和 API

state

1) vuex 管理的狀態對象
2) 它應該是唯一的
const state = {
 xxx: initValue
}

mutations

1) 包含多個直接更新 state 的方法(回調函數)的對象
2) 誰來觸發: action 中的 commit('mutation 名稱')
3) 只能包含同步的代碼, 不能寫異步代碼
const mutations = {
 yyy (state, {data1})
 {
 // 更新 state 的某個屬性
 }
}

actions

1) 包含多個事件回調函數的對象
2) 通過執行: commit()來觸發 mutation 的調用, 間接更新 state
3) 誰來觸發: 組件中: $store.dispatch('action 名稱', data1) // 'zzz'
4) 可以包含異步代碼(定時器, ajax)
const actions = {
    zzz ({commit, state}, data1){
    commit(
        'yyy', {data1}
    )
  }
}

getters

1) 包含多個計算屬性(get)的對象
2) 誰來讀取: 組件中: $store.getters.xxx
const getters = {
    mmm (state) {
        return ...
    }
}

modules

1) 包含多個 module
2) 一個 module 是一個 store 的配置對象
3) 與一個組件(包含有共享數據)對應

向外暴露 store 對象

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

組件中

import {mapState, mapGetters, mapActions} from 'vuex'
export default {
computed: {
 ...mapState(['xxx']),
 ...mapGetters(['mmm']),
}
methods: mapActions(['zzz'])
}

{{xxx}} {{mmm}} @click="zzz(data)"

映射 store
import store from './store'
new Vue({
    store
})

store 對象

1) 所有用 vuex 管理的組件中都多了一個屬性$store, 它就是一個 store 對象
2) 屬性: state: 註冊的 state 對象 getters: 註冊的 getters 對象
3) 方法: dispatch(actionName, data): 分發調用 action

實際案例

store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
/*state 對象 類似於 data */
const state = {
  count: 0
  // 初始化狀態數據
}
/*
mutations 對象包含個方法: 
能直接更新 state 一個方法就是一個 mutation mutation 
只能包含更新 state 的同步代碼, 也不會有邏輯 
mutation 由 action 觸發調用: commit('mutationName') 
*/
const mutations = {
  INCREMENT(state) {
    state.count++
  },
  DECREMENT(state) {
    // ctrl + shift + x 
    state.count--
  }
}
/*
actions 對象 包含個方法: 觸發 mutation 調用, 
間接更新 state 一個方法就是一個 action action 
中可以有邏輯代碼和異步代碼 action 由組件來觸發調用: 
this.$store.dispatch('actionName') 
*/
const actions = {
  increment({
    commit
  }) {
    commit('INCREMENT')
  },
  decrement({
    commit
  }) {
    commit('DECREMENT')
  },
  incrementIfOdd({
    commit,
    state
  }) {
    if (state.count % 2 === 1) {
      commit('INCREMENT')
    }
  },
  incrementAsync({
    commit
  }) {
    setTimeout(() => {
      commit('INCREMENT')
    }, 1000)
  }
}
/*getters 對象 包含多個 get 計算計算屬性方法 */
const getters = {
  oddOrEven(state) {
    return state.count % 2 === 0 ? '偶數' : '奇數'
  },
  count(state) {
    return state.count
  }
}
// 向外暴露 store 實例對象 
export default new Vuex.Store({
  state,
  mutations,
  actions,
  getters
})

main.js

import Vue from 'vue'
import app from './app.vue'

import store from './store'
// 創建 vue 配置路由器 
new Vue({
  el: '#app',
  store,
  render: h => h(app)
})

app.vue(未優化前)

<template>
  <div>
    <p>clicked: {{$store.state.count}} times, count is {{oddOrEven}}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">increment if odd</button>
    <button @click="incrementAsync">increment async</button>
  </div>
</template> <script>
export default {
  computed: {
    oddOrEven() {
      return this.$store.getters.oddOrEven;
    }
  },
  methods: {
    increment() {
      this.$store.dispatch("increment");
    },
    decrement() {
      this.$store.dispatch("decrement");
    },
    incrementIfOdd() {
      this.$store.dispatch("incrementIfOdd");
    },
    incrementAsync() {
      this.$store.dispatch("incrementAsync");
    }
  }
};
</script> <style>
</style>

 app2.vue(優化後)

<template>
  <div>
    <p>clicked: {{count}} times, count is {{oddOrEven2}}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">increment if odd</button>
    <button @click="incrementAsync">increment async</button>
  </div>
</template> <script>
import { mapGetters, mapActions } from "vuex";
export default {
  computed: mapGetters({
    // 名稱不一樣
    oddOrEven2: "oddOrEven",
    count: "count"
  }),
  methods: mapActions([
    "increment",
    "decrement",
    "incrementIfOdd",
    "incrementAsync"
  ]) // 名稱一樣
};
</script> 
  <style>
</style>
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章