vue之vuex

一,前言

1.Vuex是专门为Vue设计的状态管理库,集中管理所有组件的状态并与相应的规则保证状态以一种可预测的方式发生变化。

2.Vuex解决了多个组件共享状态时,传参方式繁琐,代码维护困难的问题。

二,初始化+注册

1.Vuex的入口是storestoreVuex核心概念,像一个容器仓库集中管理了所有组件的state,在Vuex4中,我们使用createStore 初始化一个store

2.createStore接受一个对象作为参数,对象中定义了组件的state和改变state的规则

import { createApp } from "vue";
import { createStore } from 'vuex';
const store = createStore({...option})
const app = createApp(/*单文件组件*/)
app.use(store )

3.Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状,这也意味着,每个应用将仅仅包含一个 store 实例

import { createApp } from "vue";
import {createStore} from 'vuex';
const store = createStore({...option})
const store1 = createStore({...option})
const app = createApp(/*单文件组件*/)
app.use(store)
app.use(store1) //当我们初始化两个store时,会根据代码执行顺序保留最后的,其余的无效

三,store介绍

1.一个完整的store包含5个配置项

(1)状态:state
(2)计算属性:getters
(3)同步修改:mutations
(4)异步修改:actions
(5)模块化:modules

2.当我们全局注册了store

app.use(store)

(1)在vue2中,我们通过组件实例的$store属性访问store仓库

this.$store

(2)在vue3中,使用组合式api

import { useStore } from 'vuex'
const store = useStore()   //useStore()等同于vue2中的$store

四,状态:state

1.state用于声明组件的状态。

2.我们使用函数形式来定义state

const store = createStore({
	state(){
		return {
			name:'Mr.poto',
			age:'20',
		}
	},
})

3.Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态。

(1)在组件中使用vuexstate数据(vue3

<script setup>
	import { computed } from 'vue';
	import { useStore } from 'vuex';
	const store = useStore()
	const age =computed(()=>store.state.age)
	const name=computed(()=>store.state.name)
</script>

(2)在组件中使用vuexstate数据(vue2

<script>
	export default {
		computed:{
			age:()=>this.$store.state.name
		}
	}
</script>

4.虽然通常我们使用computed来处理这个响应式,但是直接将状态写进视图也是可以的。

5.在vue2中当使用状态较多时可以使用辅助函数mapState简写,

<script>
	import { mapState } from 'vuex'
	export default {
		computed:{
			age:()=>this.$store.state.name,
			...mapState({
				count: state => state.count,
				aliasCount:'count',
			    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    			countPlusLocalState (state) {
     			 return state.count + this.localCount
   			 }
			})
		}
	}
</script>

6.在vue3中暂不支持vue2中辅助函数的写法

四,派生状态:getters

1.有时我们需要使用状态的派生状态,当只有一个组件需要使用时,我们可以使用计算属性,但如果有多个组件需要用到此属性,如果还使用组件的计算属性,我们就要一直复制这个函数。getter好像store的计算属性,我们只需定义一次即可。

2.定义getter:

const store = createStore({
	getters:{
		info:(state)=>state.age + state.name //接受 state 作为其第一个参数
		moreinfo:(state,getters)=>state.age + state.name + getters.info//接受 getter 作为其第二个参数
		setName:(state)=>((p)=>state.name + p) //可以通过返回一个函数来接受自定义参数
	},
})

3.使用getters:

(1)使用属性的形式

<script>
	export default {
		computed:{
			info:()=>this.$store.getters.info
		}
	}
</script>

(2)使用方法的形式

<script>
	export default {
		computed:{
			name:()=>this.$store.getters.setName('zjl')
		}
	}
</script>

4.当使用的getters较多时可以使用辅助函数mapGetters简写,

<script>
	import { mapGetters } from 'vuex'
	export default {
		computed:{
			age:()=>this.$store.state.name,
			...mapState({
				count: state => state.count,
				aliasCount:'count',
			    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    			countPlusLocalState (state) {
     			 return state.count + this.localCount
   			 }
			}),
			...mapGetters (["info","setName"])
		}
	}
</script>

五,修改状态:mutations

1.mutations是用于定义修改state的函数,且是唯一能修改state的地方

2.mutations中的函数必须是同步的。

3.mutations函数第一个参数是state,第二个参数是载荷payload,无返回值,修改state时,state地址不能变。

const store = createStore({
	state:{
		count:1,
	},
	mutations:{
		add(state){ //定义count自增的规则
			state.count=count+1 //修改时state地址不能变,否则无法相应,例如state={...state,a:111}不行
		}
		addByParams(state,payload){ //定义count根据传入参数增加的规则
			state.count =state.count+payload.num
		}
	},
})

4.我们使用store实例的commit方法来触发mutations

5.在commit里我们需要通过type指明触发那个mutations,通过payload传递参数,有如下两种形式

store.commit("add",{count:1})
store.commit({type:"add",payload:{num:2}) 

6.在vue2中,我们可以使用mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用

import { mapMutations } from 'vuex'

export default {
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

六,异步操作:actions

1.actions支持异步操作

2.actions里,我们以函数形式定义需要异步操作的业务,如需要在异步操作后修改 state、执行下一个actions等等

3.actions函数接受两个参数

(1)第一个参数接受一个与 store 实例具有相同方法和属性的 context 对象

在这里插入图片描述
(2)第二个参数是提交荷载。

const store = createStore({
	state:{
		count:1,
	},
	actions:{
		add(context,payload){ 
			setTimeout(()=>{
				context.commit(...)
			},100)
		},
		add({commit,dispatch,state},payload){ //可以将context解构出来
				setTimeout(()=>{
				commit(...)
			},100)
		}
	},
})

4.actions里的函数调用需要使用store实例的dispatch方法type表明要使用的具体actionspayload是传递的参数

this.$store.dispatch({type:"add",payload:{num:1}})

5.在vue2中,我们可以使用mapActions 辅助函数将组件中的 methods 映射为 store.dispatch 调用

import { mapActions} from 'vuex'

export default {
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

6.当我们在actions里使用async函数或者返回promise对象时,就可以组合actions

actions: {
  async actionA ({ commit }) {
    commit('gotData',)
  },

this.$store.dispatch("actionA").then()

六,模块化:module

1.由于store是单例的,当项目较大时,所有state写在一起会不够清晰又庞大,为了解决以上问题,Vuex 允许我们将 store 分割成模块。

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

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

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

2.模块内部的 actionmutation 仍然是注册在全局命名空间的——这样使得多个模块能够对同一个 actionmutation 作出响应。Getter 同样也默认注册在全局命名空间

3.如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块,同时在访问时也要加上相应的路径

4.注意,不管以任何方式分割了多个模块,都只有一个store实例,且各个模块一定可以相互访问的

七,完整数据流

1.一个完整的数据流如下图所示
在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值