Day24-Vuex核心概念与结构(part2)

接续前面的内容,还有几个东西没有研究到...

3. mutations

前面是学到的向仓库取资料的办法,再来就是要学怎麽写资料进去仓库。唯一方法是提交(commit)某个mutations属性,在里面定义一个function和callback,其中有两个参数,分别为state与payload(传递进来的值)。

state: {
    product: 't-shirt',
    price: 500,
    quantity: 100
  },
mutations: {
  setQuantity(state, payload) {
    state.quantity = payload
  }
},

若今天要更新state.quantity时,可以在元件新增且绑定到按钮点击事件上。点击按钮,元件会提交(commit) setQuantity给mutations,再把this.qty传出去。

<template>
  <input type="text" v-model.number="qty" />
	 <button @click="unpdateQty">Click</button>
</template>

<script>
export default {
  data() {
    return {
      qty: 0,
    };
  },
  methods: {
    updateQty() {
      this.$store.commit("setQuantity", this.qty);
    },
  },
};
</script>

另外,想要传物件的话,可以这样写

this.$store.commit({
	type: 'setQuantity',
	qty: this.qty
})

对应的mutations也要改

mutations: {
  setQuantity(state, payload) {
    state.quantity = payload.qty
  }
},

mapMutations

和前两个一样。透过mapMutations将setQuantity引入元件,mapMutations回传一个对应的setQuantity方法,并自动带入payload功能。

<template>
  <input type="text" v-model.number="qty" />
	//此处有多带参数
  <button @click="setQuantity(qty)">Click</button>
</template>

<script>
import { mapMutations } from "vuex";

export default {
  data() {
    return {
      qty: 0,
    };
  },
  methods: {
    ...mapMutations(["setQuantity"]),
  },
};
</script>

注意!! mapMutations中所有操作必须为同步,故无法在里面使用async/await或promise等非同步操作。

4. actions

作用类似mutations,但不能直接操控state的资料,也因此在这里可以执行非同步的任务,再把结果传回mutations去改资料。

接续范例,state.product变成空物件,在actions加上fetchProductInf函式

state: {
    product: {}
  },
actions: {
  fetchProductInfo(context,payload){
		//假设API回传{"id":"123", "name": "t-shirt", "price": 500, "quantity": 100}
    fetch('...')
			.then(res=>res.json)
			.then(data=>context.commit('setProductInfo',data))
  }
},

actions中有两个参数 :

  • context : 与Vuex实体相同的物件,非store本人,但可以透过呼叫他对store进行操作。如果想要某个actions去dispatch另一个actions时,可以透过context.dispatch('...')来完成。
  • payload : 和先前的一样,外部传入的值。
export default {
  created() {
    this.$store.dispatch("setProductInfo", { id: "001" });
  },
};

fetchProductInfo在created或mounted阶段(也就是实体被建立)被dispatch,会透过API对後端发送邀请,并回传API结果透过context.commit()提交给setProductInfo。

mapActions

Actions也又自己的mapActions可以用,用下面的写法也可以得到刚刚的结果。

import { mapActions } from "vuex";

export default {
  methods: {
    ...mapActions(['fetchProductInfo'])
  },
  created() {
    this.fetchProductInfo({ id: "001" });
  },
};

5. modules

在结构图没有却在建立的src/store/index.js中出现的module。他的功能就是管理不断扩大的state资料。

在modules里面可以将store拆成两块,moduleA和moduleB。

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

export default createStore({
	state:{ ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... },
	modules: {
	    moduleA,
		  moduleB
  }
})

在vue元件时,可以透过mapState取得state.moduleA的资料

computed:{
	...mapState({
		productA:(state)=>store.moduleA.product,
		productB:(state)=>store.moduleB.product
	})
}

rootState

拆成两个模组後,可以透过rootState取得外层store的资料。

const moduleA= {
	state: ()=>({...}),
  getters: {
    // 需透过第三和四的参数取得rootState、rootGetters
    sumWithRootCount (state, getters, rootState) {
    return state.count + rootState.count
    }
  },
	mutations: {
		//可以透过context存取context.rootState
    increment ({state,commit,rootState}) {
     //...
    }
  },
	actions:{
		//可以透过context存取context.rootState
		incrementIfOddOnRootSum({ state, commit, rootState} = context;
			if((state.count + rootState.count)% 2 === 1){
				commit('increment')
			}
		}
	}
}

namespaced

当模组有相同名称的actions时,

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: {
		fetchProductInfo(){...}
	},
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: {
		fetchProductInfo(){...}
	},
}

元件下dispatch时两个会同时被呼叫

this.$store.dispatch('fetchProductInfo')

namespaced可以避免因相同命名而犯的错误。

const moduleA = {
	namespaced: true,
  state: () => ({ ... }),
  mutations: { ... },
  actions: {
		fetchProductInfo(){...}
	},
}

const moduleB = {
	namespaced: true,
  state: () => ({ ... }),
  mutations: { ... },
  actions: {
		fetchProductInfo(){...}
	},
}

呼叫的时候就不会找错人

// moduleA 的 fetchProductInfo 
this.$store.dispatch('moduleA/fetchProductInfo'); 
// moduleB 的 fetchProductInfo 
this.$store.commit('moduleB/fetchProductInfo');

//OR 采用mapActions,mapMutations指定namespaced到第一个参数
methods: { 
	...mapActions('moduleA', ['fetchProductInfo', '...']), 
	...mapMutations('moduleB', ['updateProductInfo', '...']), 
},

模组也有机会dispatch或commit到root,此时只需要加入第三个参数:

dispatch('someOtherActions', null, {root:true})
commit('someMutation', null, {root:true})

参考资料

图解 Vuex 统一状态管理
https://chineseplease.moe/wp-content/uploads/2020/04/Vuex.png


<<:  [Day24] Array methods 阵列操作方法(2)

>>:  30天学会C语言: Day 23-被消失的型别

Day 28:1. Two Sum

今日题目 题目连结:1. Two Sum 题目主题:Array, Hash Table 简单说说 H...

22 准备完成後跳转到游戏页面

两个人都准备好的时候,要转到游戏画面 我来把准备画面跟游戏分开好了 这样比较不会什麽都塞在同一个 l...

全端入门Day01_前言

今天是铁人赛的第一天,这是我第一次参赛,之前听了很多同学说这是个需要有毅力的比赛,我相信我一定能够撑...

三种时间长短,让你简单培养习惯

昨天有点晚睡,睡前还很害怕会不会又失败持续的一天XD 但幸好还是有继续努力运动。 闹钟一响就起床,...

[Day30] GCP云端部属说明(前後端)

How - 部属MongoDB 登入以下网址 https://www.mongodb.com/clo...