Vuex從入門到精通

来源:https://www.cnblogs.com/P1Kaj1uu/archive/2022/12/22/16997722.html
-Advertisement-
Play Games

一、vuex介紹 目標 什麼是Vuex 為什麼學習Vuex 通信方案 | 組件關係 | 數據通信 | | | | | 父子關係 | 父傳子:props ; 子傳父:$emit | | 非父子關係 | vuex (一種組件通信方案) | Vuex是什麼 概念:專門在 Vue 中實現集中式狀態(數據)管 ...


一、vuex介紹

目標
  • 什麼是Vuex
  • 為什麼學習Vuex
通信方案

組件關係 數據通信
父子關係 父傳子:props ; 子傳父:$emit
非父子關係 vuex (一種組件通信方案)
Vuex是什麼
  • 概念:專門在 Vue 中實現集中式狀態(數據)管理的一個 Vue 插件,對 vue 應 用中多個組件的共用狀態進行集中式的管理(讀/寫),也是一種組件間通信的方 式,且適用於任意組件間通信。

  • Vuex 實現了一個單向數據流,在全局擁有一個 State 存放數據,當組件要更改 State 中的數據時,必須通過 Mutation 提交修改信息, Mutation 同時提供了訂閱者模式供外部插件調用獲取 State 數據的更新。而當所有非同步操作(常見於調用後端介面非同步獲取更新數據)或批量的同步操作需要走 Action ,但 Action 也是無法直接修改 State 的,還是需要通過Mutation 來修改State的數據。最後,根據 State 的變化,渲染到視圖上。

    • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地得到高效更新。
    • 改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣可以方便地跟蹤每一個狀態的變化。
  • 原理如圖所示:

vuex為何學

程式頁面多, 數據變數多

  1. 不同組件數據保持同步
  2. 數據的修改都是可追蹤

一個戶外商店有兩名員工,張三和李四

一天的早上,他們分別對帳篷的數量做了一次盤點,發現一共有三個帳篷

張三賣出去倆個,他以為庫存里還有一個

李四賣出去一個,他以為庫存里還有兩個

而事實上是,庫存現在已經為

如果他們再接受客戶的預訂,就會出現庫存不足的情況

張三和李四因為沒有保持庫存的數量的同步導致了尷尬,這個就是所謂的數據保持同步

店長需要知道, 誰賣出了多少個帳篷,這個行為我們稱之為數據修改是可追蹤的

圖示:

Vuex中存什麼

多個組件共用狀態,才存儲在Vuex中

某個組件中的私有數據,依舊存儲在data中

例如:

  • 登陸的用戶名需要在首頁, 個人中心, 結算頁面使用, 用戶名存在Vuex中

  • 文章詳情數據, 只有在文章詳情頁查看, 在自身data中聲明

小結
  1. 什麼是Vuex
    • Vuex是Vue官方推薦的集中式狀態管理機制
  2. 為何學Vuex
    • 數據同步, 集中管理
  3. Vuex中存什麼
    • 多個組件共用的值

二、Vuex學習內容

目標
  • 知道Vuex要學習什麼
核心概念
  1. 官網地址: https://vuex.vuejs.org/zh/

  2. 安裝(固定)

  3. 配置項(固定)

    配置項 含義 註意
    state 單一狀態樹 類似data
    mutations 數據管家(同步) 唯一修改state地方
    actions 非同步請求 要改state需要提交給mutations
    getters vuex計算屬性 類似computed
    modules 模塊拆分
圖示關係

單一定義store對象, 裡面5個配置項, 在任意組件可以使用

小結
  1. Vuex五個核心概念是?
    • state / mutations / actions / getters / modules

三、Vuex例子準備

目標
  • 創建項目, 為學習準備

    • 需求1: App.vue(作為根組件)

    • 需求2: 子組件Add和子組件Sub, 嵌入在App.vue里

    • 需求3: 三個組件共用庫存數據(保持同步)

工程準備
  1. 初始化新的工程 vuex-demo

    vue create vuex-demo
    
  2. 清空歡迎界面

  3. 並設置如下三個組件, 目錄如下:

    |-components
    |---AddItem.vue
    |---SubItem.vue
    |-App.vue
    
App.vue

複製標簽和樣式, 引入AddItem和SubItem2個子組件顯示

<template>
  <div id="app">
    <h1>根組件</h1>
    <span>庫存總數:</span>
    <input type="text">
    <div style="border:1px solid black; width: 300px;">
      <AddItem></AddItem>
    </div>
    <hr>
    <div style="border:1px solid black; width: 300px;">
      <SubItem></SubItem>
    </div>
  </div>
</template>

<script>
import AddItem from '@/components/AddItem'
import SubItem from '@/components/SubItem'
export default {
  components: {
    AddItem,
    SubItem
  }
}
</script>

<style>
#app {
  width: 300px;
  margin: 20px auto;
  border:1px solid #ccc;
  padding:4px;
}
</style>
AddItem.vue
<template>
  <div>
      <h3>AddItem組件</h3>
      <p>已知庫存數: 0</p>
      <button>庫存+1</button>
  </div>
</template>

<script>
export default {

}
</script>
SubItem.vue
<template>
  <div>
      <h3>SubItem組件</h3>
      <p>已知庫存數: 0</p>
      <button>庫存-1</button>
  </div>
</template>

<script>
export default {

}
</script>
小結
  1. App下套用了AddItem和SubItem, 要在3個組件共用一個數據

四、vuex-store準備

目標
  • 創建store倉庫
  • 註入到Vue項目中
store概念

每個 Vuex 應用的核心 store(倉庫), 包含5個核心概念

Vuex目錄

和路由模塊router/index.js - 類似, 維護項目目錄的整潔,新建src/store/index.js文件

當然, 這個步驟並不是必需的

使用步驟
  1. 工程中 - 下載vuex

    yarn add vuex
    
  2. store/index.js - 創建定義導出store對象

    // 目標: 創建store倉庫對象
    // 1. 下載vuex: 終端命令(yarn add vuex)
    // 2. 引入vuex
    import Vue from 'vue'
    import Vuex from 'vuex'
    // 3. 註冊
    Vue.use(Vuex)
    // 4. 實例化store對象
    const store = new Vuex.Store({})
    // 5. 導出store對象
    export default store
    
  3. main.js - 導入註入到Vue中

    import Vue from 'vue'
    import App from './App.vue'
    import store from '@/store' // 導入store對象
    
    Vue.config.productionTip = false
    
    new Vue({
      // 6. 註入到Vue實例中(確保組件this.$store使用) // this.$store = store
      store,
      render: h => h(App),
    }).$mount('#app')
    
    

請再次回憶一下vue-router的用法,是不是很像?

小結
  1. vuex的核心是什麼?

    • store對象(包含5個核心屬性)
  2. 如何創建store對象?

    • 工程下載vuex模塊
    • store/index.js
      • 引入註冊
      • 生成store對象導出
      • main.js - 導入註入

五、vuex-state數據源

目標
  • 定義state
  • 直接使用state
  • 輔助函數mapState

state是唯一的公共數據源,統一存儲

定義state

在store/index.js定義state

語法:

/*
const store = new Vuex.Store({
    state: {
        變數名: 初始值
    }
})	
*/

具體代碼:

const store = new Vuex.Store({
    state: {
        count: 100 // 庫存
    }
})
使用state2種方式
  • 方式1: 組件內 - 直接使用

    語法:

    this.$store.state.變數名
    
  • 方式2: 組件內 - 映射使用 (推薦)

    語法:

    // 1. 拿到mapState輔助函數
    import { mapState } from 'vuex'
    export default {
        computed: {
            // 2. 把state里變數映射到計算屬性中
            ...mapState(['state里的變數名'])
        }
    }
    
AddItem直接用
<template>
  <div>
      <h3>AddItem組件</h3>
      <p>已知庫存數: {{ $store.state.count }}</p>
      <button>庫存+1</button>
  </div>
</template>
App.vue直接用

計算屬性count, 和輸入框的v-model雙向綁定

<input type="text" v-model="count">

<script>
export default {
  computed: {
    count: {
      set(){},
      get(){
        return this.$store.state.count
      }
    }
  }
}
</script>
SubItem映射用
<template>
  <div>
      <h3>SubItem組件</h3>
      <p>已知庫存數: {{ count }}</p>
      <button>庫存-1</button>
  </div>
</template>

<script>
// 需求1: 映射state到計算屬性
// 1. 拿到輔助函數 mapState
// 2. 在computed內, ...mapState(['state變數名'])
// 3. 當計算屬性使用
import { mapState } from 'vuex'
// let r = mapState(['count']) // 提取store里的state叫count的變數
// console.log(r); // 返回值: {count: 函數體(return state里count的值)}

export default {
  computed: {
    // 映射count, 得到對象展開, 合併到計算屬性中
    ...mapState(['count'])
  },
}
</script>

整個過程的示意圖如下

註意

state是響應式的, 只要state值變化, 頁面上使用的地方會自動更新同步

小結
  1. state作用?

    定義全局狀態數據源

  2. state如何定義?

    在store內, state: {變數名: 初始值}

  3. state的值如何用到具體vue組件內?

    • 直接使用 this.$store.state.變數名
    • 映射使用 ...mapState(['state的變數名'])

六、vuex-mutations定義-同步修改

目標
  • 定義mutations
定義mutations

mutations類似數據管家, 操作state里的數據

在store/index.js定義mutations

語法:

/*
const store  = new Vuex.Store({
	mutations: {
		函數名 (state, 可選值) {
			// 同步修改state值代碼
		}
	}
})
*/

具體代碼

const store  = new Vuex.Store({
    state: {
        count: 100 // 庫存
    },
	mutations: {
		addCount (state, value) { // 負責增加庫存的管家
			state.count += value
		},
        subCount (state, value) { // 負責減少庫存的管家
            state.count -= value
        },
        setCount (state, value) { // 負責直接修改庫存的管家
            state.count = value;
        }
	}
})
註意
  1. mutations是唯一能修改state的地方, 確保調試工具可以追蹤變化
  2. mutations函數內, 只能寫同步代碼, 調試工具可追蹤變化過程
    • 因為調試工具要立刻產生一次記錄, 所以必須是同步的
小結
  1. mutations里函數作用?

    • 負責修改state里的數據
  2. mutations只能寫什麼樣的代碼?

    • 同步流程的代碼

七、vuex-mutations使用

目標
  • 使用mutations2種方式
  • mutations註意事項
使用mutations的2種方式
  • 方式1: 組件內 - 直接使用

    語法:

    this.$store.commit("mutations里的函數名", 具體值)
    
  • 方式2: 組件內 - 映射使用

    語法:

    // 1. 拿到mapMutations輔助函數
    import { mapMutations } from 'vuex'
    export default {
        methods: {
            // 2. 把mutations里方法映射到原地
            ...mapMutations(['mutations里的函數名'])
        }
    }
    
AddItem直接用
  • 點擊事件綁定
  • 提交mutations傳入值
<button @click="addFn">庫存+1</button>

<script>
export default {
  methods: {
    addFn(){
      this.$store.commit('addCount', 1)
    }
  }
}
</script>
App.vue直接用
  • 觸發計算屬性的set方法
  • 提交mutations傳入值
<span>庫存總數: </span>
<input type="text" v-model="count">

<script>
export default {
  computed: {
    count: {
      set(val){
        this.$store.commit('setCount', val) // 把表單值提交給store下的mutations
      },
      get(){
        return this.$store.state.count
      }
    }
  }
}
</script>
SubItem映射用
  • 點擊事件
  • 映射mutations的方法
  • 調用mutations方法傳值
<button @click="subFn">庫存-1</button>

<script>
// 需求2: 映射mutations到方法里
// 1. 拿到輔助函數 mapMutations
// 2. 在methods內, ...mapMutations(['mutations函數名'])
// 3. 當普通方法使用

import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations(['subCount']),
    subFn(){
      this.subCount(1)
    }
  }
}
</script>
註意

mutations函數上, 只能接收一個參數值, 如果傳對個, 請傳一個對象

小結
  1. mutations有哪2種使用方式?

    直接使用 this.$store.commit()

    映射使用 mapMutations把方法映射到組件內直接調用

  2. state, mutations, 視圖組件, 3個關係是什麼?

八、vuex-actions定義-非同步修改

目標
  • 定義actions
定義actions

在store/index.js定義actions

語法:

/*
const store = new Vuex.Store({
	actions: {
		函數名 (store, 可選值) {
			// 非同步代碼, 把結果commit給mutations給state賦值
		}
	}
})
*/

具體代碼:

const store  = new Vuex.Store({
    // ...省略state和mutations此處
    actions: {
        asyncAddCount(store, num){
            setTimeout(() => { // 1秒後, 非同步提交給add的mutations
                store.commit('addCount', num)
            }, 1000)
        },
        asyncSubCount(store, num) {
            setTimeout(() => { // 1秒後, 非同步提交給sub的mutations
                store.commit('subCount', num)
            }, 1000)
        }
    }
})
小結
  1. actions和mutations區別?

    mutations里同步修改state

    actions里放入非同步操作

  2. actions是否能操作state?

    不建議, 要commit給mutations(為調試工具可追蹤)

  3. actions和mutations里函數, 第一個形參分別是什麼?

    mutations的是state

    actions的是store

九、vuex-actions使用

目標
  • 使用actions
使用actions的2種方式
  • 方式1: 組件內 - 直接使用

    語法:

    this.$store.dispatch('actions函數名', 具體值)
    
  • 方式2: 組件內 - 映射使用

    語法:

    // 1. 拿到mapActions輔助函數
    import { mapActions } from 'vuex'
    export default {
        methods: {
            // 2. 把actions里方法映射到原地
            ...mapActions(['actions里的函數名'])
        }
    }
    
AddItem直接用
  • 點擊事件
  • dispatch觸發action
<button @click="asyncAddFn">延遲1秒, 庫存+5</button>

<script>
export default {
  methods: {
    asyncAddFn(){
      this.$store.dispatch('asyncAddCount', 5)
    }
  }
}
</script>
SubItem映射用
  • 點擊事件
  • 映射actions的方法
  • 調用actions的方法傳值
<button @click="asyncSubFn">延遲1秒, 庫存-5</button>

<script>
// 需求3: 映射actions到方法里
// 1. 拿到輔助函數 mapActions
// 2. 在methods內, ...mapActions(['actions函數名'])
// 3. 當普通方法使用

import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions(['asyncSubCount']),
    asyncSubFn(){
      this.asyncSubCount(5)
    }
  }
}
</script>
小結
  1. actions使用方式?

    方式1: this.$store.dispatch('actions方法名字', 值)

    方式2: ...mapActions(['actions里的方法名']) 映射到原地使用

  2. 視圖組件, state, mutations, actions的關係是?

十、vuex-重構購物車-準備Store

目標
  • 在現有項目如何集成vuex
store準備
  1. 複製預習資料<shopcar-模板>到自己今天文件夾下
  2. 下載vuex
  3. store/index.js創建導出store對象
  4. main.js把store引入, 然後註入到Vue實例
小結
  1. 現有項目如何集成vuex

    下載vuex

    創建store對象並註入到Vue實例中

十一、vuex-重構購物車-配置項(上午結束)

目標
  • 準備state和mutations還有actions
配置項準備
  1. 定義state - 保存商品列表數組
state: {
    goodsList: [] // 列表
}
  1. 定義mutations - 給state里變數賦值
mutations: {
    setGoodsList(state, newList) {
        state.goodsList = newList
    }
}
  1. 定義actions - 非同步請求數據提交給mutations
actions: {
    async asyncGetGoodsList(store) {
        const url = `https://www.escook.cn/api/cart`
        // 發送非同步請求
        const res = await axios({ url: url });
        store.commit('setGoodsList', res.data.list) // 提交mutation修改state中的數據
    }
}
App.vue使用vuex
  • 把vuex商品數組映射回來使用
  • 網路請求調用actions方法
<script>
import { mapState, mapActions } from 'vuex'
export default {
  computed: {
    ...mapState({list: 'goodsList'}) // 自定義原地屬性名list, 映射vuex里的goodsList變數值
  },
  created(){
    this.asyncGetGoodsList()
  },
  methods: {
    ...mapActions(['asyncGetGoodsList']),
    allFn(bool){
      this.list.forEach(obj => obj.goods_state = bool)
    }
  }
}
</script>
小結
  1. mapState可以改變映射到原地的計算屬性名嗎?

    可以的, 格式...mapState({''計算屬性名', 'state里要映射的變數名'})

十二、vuex-getters定義-計算屬性

目標
  • getters概念
  • 定義getters
getters概念

vuex身上的全局狀態-計算屬性, 類似於computed

getters 依賴於 state中原始數據的變化,並返回計算後的新數據

定義getters

在store/index.js定義getters

語法:

/*
const store = new Vuex.Store({
	getters: {
		計算屬性名 (state) {
			return 值給計算屬性
		}
	}
})
*/

具體代碼

const store = new Vuex.Store({
    // ...省略其他
    getters: {
        allCount(state) {
            return state.goodsList.reduce((sum, obj) => {
                if (obj.goods_state === true) { // 選中商品才累加數量
                    sum += obj.goods_count;
                }
                return sum;
            }, 0)
        },
        allPrice(state) {
            return state.goodsList.reduce((sum, obj) => {
                if (obj.goods_state) {
                    sum += obj.goods_count * obj.goods_price
                }
                return sum;
            }, 0)
        }
    }
})
小結
  1. getters有什麼用?

    vuex里的計算屬性, 屬於全局計算屬性, 類似computed

十三、vuex-getters使用

目標
  • 組件內使用getters
使用getters的2種方式
  • 方式1: 組件內 - 直接使用

    語法:

    this.$store.getters.計算屬性名
    
  • 方式2: 組件內 - 映射使用

    語法:

    // 1. 拿到mapGetters輔助函數
    import { mapGetters } from 'vuex'
    export default {
    	computed: {
            // 2. 把getters里屬性映射到原地
          ...mapGetters(['getters里的計算屬性名'])
        }   
    }
    
MyFooter.vue里使用
  • 使用2種方式給計算屬性值
<script>
import { mapGetters } from 'vuex'
export default {
  computed: {
    allCount(){
     return this.$store.getters.allCount;
    },
    ...mapGetters(['allPrice'])
  }
}
</script>
小結
  1. getters如何使用?

    方式1: this.$store.getters.計算屬性名

    方式2: ...mapGetters(['getters里計算屬性名'])

十四、vuex-modules定義-分模塊

目標
  • 為何要分模塊
  • modules定義
為何分模塊

代碼上的對比

創建modules模塊對象
  • 新建store/modules/user.js
  • 新建store/modules/cart.js

語法: 對象里包含5個核心概念, 只有state變成函數形式

user.js - 用戶模塊對象

// 用戶模塊對象
const userModule = {
    state(){
        return {
            name: "",
            age: 0,
            sex: ''
        }
    },
    mutations: {},
    actions: {},
    getters: {}
}
export default userModule

cart.js - 購物車模塊對象

// 購物車模塊對象
import axios from 'axios'
const cartModule = {
    state() {
        return {
            goodsList: []
        }
    },
    mutations: {
        setGoodsList(state, newList) {
            state.goodsList = newList
        }
    },
    actions: {
        async asyncGetGoodsList(store) {
            const url = `https://www.escook.cn/api/cart`
            // 發送非同步請求
            const res = await axios({ url: url });
            store.commit('setGoodsList', res.data.list) // 提交mutation修改state中的數據
        }
    },
    getters: {
        allCount(state) {
            return state.goodsList.reduce((sum, obj) => {
                if (obj.goods_state === true) { // 選中商品才累加數量
                    sum += obj.goods_count;
                }
                return sum;
            }, 0)
        },
        allPrice(state) {
            return state.goodsList.reduce((sum, obj) => {
                if (obj.goods_state) {
                    sum += obj.goods_count * obj.goods_price
                }
                return sum;
            }, 0)
        }
    }
}
export default cartModule
定義modules

語法:

modules: {
    模塊名: 模塊對象
}
  • 把2個模塊對象, 引回到store里註冊
import Vue from 'vue'
import Vuex from 'vuex'
import cartModule from './modules/cart'
import userModule from './modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
    modules: {
        user: userModule,
        cart: cartModule
    }
})
export default store
小結
  1. 為什麼分模塊?

    集中式管理項目過大, 變數過多, 會導致state臃腫, 難以維護

  2. 如何分模塊?

    定義模塊對象, state變成函數返回對象形式, 每個模塊都有state/mutations/actions/getters/modules

  3. 根store如何註冊?

    modules里 { 模塊名: 模塊對象 }

十五、分模塊-影響state取值方式

目的
  • 只要分模塊, state取值方式改變, 其他暫時不變
state使用方式修改
  • 方式1: 組件內 - 直接使用

    原語法:

    this.$store.state.變數名
    

    分模塊後語法:

    this.$store.state.模塊名.變數名
    
  • 方式2: 組件內 - 映射使用

    原語法:

    ...mapState(['state里變數名'])
    ...mapState({'變數名': "state里變數名"}) // 給映射過來的state起別的名字
    

    分模塊後語法:

    ...mapState({
        '變數名': state => state.模塊名.變數名
    })
    
App.vue-修改
computed: {
    // ...mapState({list: 'goodsList'}) // 本地屬性名list, 映射vuex里的goodsList變數值
    // 方式1: 直接用
    // list(){ // 這個list就是組件內普通的計算屬性名
    //     return this.$store.state.cart.goodsList 
    // }.
    // 方式2: 映射方式改變
    ...mapState({'list': state => state.cart.goodsList})
},
小結
  1. 分模塊對什麼有影響?

    對state的取值方式有影響, 對其他暫無影響

  2. state如何取值?

    在組件使用的時候, 要state.模塊名.變數名

十六、分模塊-命名空間

目標
  • 防止多個模塊之間, mutations/actions/getters的名字衝突
開啟命名空間

在模塊對象內設置namespaced: true

const moduleShopCar = {
    namespaced: true,
    state () {},
    mutations: {},
    actions: {},
    getters: {},
    modules: {}
}
state使用方式修改
  • 直接使用無變化: this.$store.state.模塊名.變數名

  • 輔助函數需要遵守格式

    ...mapState("模塊名", ['state變數名'])
    
mutations使用方式修改
  • 方式1: 組件內 - 直接使用

    • 原語法:

      this.$store.commit("mutations里的函數名", 具體值)
      
    • 開命名空間後語法:

      this.$store.commit("模塊名/mutations里的函數名", 具體值)
      
  • 方式2: 組件內 - 映射使用

    • 原語法:

      ...mapMutations(['mutations里方法名'])
      
    • 開命名空間後語法:

      ...mapMutations("模塊名", ['mutations里方法名'])
      
actions使用方式修改
  • 方式1: 組件內 - 直接使用

    • 原語法:

      this.$store.dispatch("actions里的函數名", 具體值)
      
    • 開命名空間後語法:

      this.$store.dispatch("模塊名/actions里的函數名", 具體值)
      
  • 方式2: 組件內 - 映射使用

    • 原語法:

      ...mapActions(['actions里方法名'])
      
    • 開命名空間後語法:

      ...mapActions("模塊名", ['actions里方法名'])
      
getters使用方式修改
  • 方式1: 組件內 - 直接使用

    • 原語法:

      this.$store.getters.計算屬性名
      
    • 開命名空間後語法:

      this.$store.getters['模塊名/計算屬性名']
      
  • 方式2: 組件內 - 映射使用

    • 原語法:

      ...mapGetters(['getters里計算屬性名'])
      
    • 開命名空間後語法:

      ...mapGetters("模塊名", ['getters里計算屬性名'])
      
小結
  1. state和mutations, 在根store和開啟命名空間里的區別?

image-20210604084953510

  1. 整個vuex的體系是?

    image-20210624225100101

十七、Vuex的構造

1.actions
  • 由子組件this.$store.dispatch('actions名',傳遞的數據)觸發
  • 傳遞的數據只能是單個數據,多個數據用對象傳遞
  • actions: { action名({commit},數據){...}}
  • store中actions內,commit用於觸發mutations,actions只做業務邏輯,不修改state
2.mutations
  • 由actions中的commit('mutations名',傳遞的數據)觸發
  • mutations:{mutations名(state,數據){...}}
  • store中的mutations內,mutations可以修改state中的數據
3.state
  • 存儲數據:state:{userInfor:{}}
  • 可以通過mutations存儲或者修改,也是getters裡面計算屬性的依據
4.getters
  • 計算state中的數據:getters:{getters名(state){...}}
  • state用於getters計算屬性的依據

十八、Vuex中的模塊(module)和命名空間(namespaced)

1.模塊(module)
  • 由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常複雜時,store 對象就有可能變得相當臃腫。
    為瞭解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的state、mutations、actions、getters、甚至是嵌套子模塊。
2.命名空間(namespaced)
  • 預設情況下,模塊內部的 actions、mutations 和 getters 是註冊在全局命名空間的——這樣使得多個模塊能夠對同一 mutations 或 actions 作出響應,如果希望你的模塊具有更高的封裝度和復用性,你可以通過添加 namespaced: true 的方式使其成為帶命名空間的模塊。當模塊被註冊後,它的所有 getters、actions 及 mutations 都會自動根據模塊註冊的路徑調整命名。

  • 如果你想模塊之間相互獨立、互不影響。可以通過添加 namespaced: true 的方式使其成為帶命名空間的模塊,當模塊被註冊後,它的所有 getters、actions 和 mutations 都會自動根據模塊註冊的路徑調整命名。所以開啟命名空間的模塊中的getters、actions 和 mutations的使用方式都會改變;但是開啟命名空間和不開啟命名空間的模塊中的state的使用方式不會改變。格式依然是store.state.模塊名.狀態名。

    // 開啟store子模塊的命名空間
    const moduleName = {
    	state: {},
    	getters: {},
    	mutations: {},
    	actions: {},
    	namespaced: true	// 開啟命名空間
    }
    export default moduleName
    
    // 在組件中使用
    import { mapState, mapGetters, mapActions } from 'vuex'
    export default {
    	computed: {
    		// 傳統方式:獲取store中的數據
    		proData () {
    			return this.$store.state.productModule.proData
    		},
    		themeData () {
    			return this.$store.getters['themeModule/themeData']
    		},
    		proName () {
    			return this.$store.getters['productModule/proName']
    		},
    		proDesc () {
    			return this.$store.getters['productModule/proDesc']
    		},
    		indexData () {
    			return this.$store.getters['productModule/indexData']
    		}
    		// 輔助函數方式一:獲取store中的數據(代碼較簡潔)
    		...mapState({ proData: state => state.productModule.proData })
    		...mapGetters(['themeModule/themeData'])
    		...mapGetters(['themeModule/proName', 'themeModule/proDesc', 'themeModule/indexData'])
    		// 輔助函數方式二:獲取store中的數據(代碼最簡潔)
    		...mapState('productModule', { proData: state => state.proData })
    		...mapGetters('themeModule', ['themeData'])
    		...mapGetters('productModule', ['proName', 'proDesc', 'indexData'])
    	},
    	created () {
    		// 傳統方式:獲取非同步數據
    		this.$store.dispath('themeModule/queryThemeAction')
    		this.$store.dispath('productModule/queryProDataAction')
    		this.$store.dispath('productModule/queryIndexDataAction')
    		// 輔助函數方式:獲取非同步數據(需要在methods中使用mapActions定義方法)
    		this.queryThemeAction()
    		this.queryProDataAction()
    		this.queryIndexDataAction()
    	},
    	methods: {
    		...mapActions('themeModule', ['queryThemeAction'])
    		...mapActions('productModule', ['queryProDataAction', 'queryIndexDataAction'])
    	}
    }
    

擴展: 使用Devtools調試vuex數據

優秀的調試工具可以使我們寫程式事半功倍,最後我們再學習一下如果使用dev-tools來調試vuex中的數據,這也是數據可預測特性里不可缺少的一環

目標
  • 掌握dev-tools調試vuex
  • 理解什麼是數據狀態是可追蹤的
如何進行調試

註意只有vue+vuex的項目才可以用

調試信息說明


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文簡介 點贊 + 關註 + 收藏 = 學會了 fabric.js 為我們提供了很多厲害的方法。今天要搞明白的一個東西是 canvas.interactive 。 官方文檔對 canvas.interactive 的解釋是: Indicates that canvas is interactive. ...
  • 案例介紹 歡迎來的我的小院,我是霍大俠,恭喜你今天又要進步一點點了!我們來用JavaScript編程實戰案例,做一個滑鼠愛心特效。滑鼠在頁面移動時會出現彩色愛心特效。通過實戰我們將學會createElement方法、appendChild方法、setTimeout方法。 案例演示 頁面出現後,滑鼠在 ...
  • HTML 介紹 引用 最全面的前端筆記來啦,包含了入門到入行的筆記,還支持實時效果預覽。小伙伴們不需要在花時間去寫筆記,或者是去網上找筆記了。面試高頻提問和你想要的筆記都幫你寫好了。支持移動端和PC端閱讀,深色和淺色模式。 原文鏈接:https://note.noxussj.top/ ::: war ...
  • 案例介紹 歡迎來到我的小院,我是霍大俠,恭喜你今天又要進步一點點了!我們來用JavaScript編程實戰案例,做一個大轉盤。當你難以抉擇的時候不妨用這個案例來幫你做選擇。通過編程實戰我們可以學到按鈕的點擊事件onclick()以及定時器的使用. 案例演示 每個選擇都展示在不同的盒子里,通過點擊中間的 ...
  • 原型鏈與繼承 new 關鍵字的執行過程 讓我們回顧一下,this 指向里提到的new關鍵字執行過程。 創建一個新的空對象 將構造函數的原型賦給新創建對象(實例)的隱式原型 利用顯式綁定將構造函數的 this 綁定到新創建對象併為其添加屬性 返回這個對象 手寫new關鍵字的執行過程: function ...
  • Visual Studio Code 介紹 Visual Studio Code 是一款非常輕量的前端代碼編寫工具,也是目前比較主流的。其中還包含了豐富的插件市場、非常好看的界面風格、可在軟體內直接使用命令行工具等。 :::warning 建議 在學習前端之前可以先把軟體下載好,方便實踐操作。 :: ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 本文作者:霜序(LuckyFBB) 前言 在之前的文章中,我們講述了 React 的數據流管理,從 props → context → Redux,以及 Redux 相 ...
  • //模擬對象 let obj = { numberParams:1, functionParams:() => { console.log('昨天基金全是綠的,只有我的眼睛是紅的'); }, objParams:{ a:1, b:2 } } const newObj = copyObj(obj); ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...