Vuex 入门笔记

(一) Vuex 概述

Vuex : 是一个专为Vue.js 应用程序开发的状态管理模式, 它采用集中式存储管理应用的所有组件的状态, 并以相应的规则保证状态以一种可预测的方式发生改变.

即: 状态管理对象, 存储管理着一些共享的状态对象(如: 登录令牌token、URL路由地址…), 以供各个组件使用、响应式的修改

Vuex应用的核心是store(仓库), store 基本上就是一个容器对象, 它里面存储管理着可共享的state(状态)

Vuex和全局对象的区别:

  • Vuex的状态存储是响应式的, 若 store 中的state状态发生改变, 那么相应的组件也会相应地得到更新
  • Vuex 官方不建议直接修改store中的state状态, 改变store中的state状态的唯一途径: commit提交mutation

在这里插入图片描述


(二) Vuex 基本使用

1. vuex 安装

通过命令安装vuex依赖, 也可以通过VueCli脚手架安装

npm install vuex --save

2. vuex 基本架构

在src下创建文件: /src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

// 1. 通过Vue.use(插件), 安装插件
Vue.use(Vuex)

// 2.创建Vuex.Store对象并导出, 以供Vue实例使用
export default new Vuex.Store({
   // state: Vuex存储的状态共享对象
   state: {
      count: 100
   },
   mutations: {

   }, 
   actions: {
      
   },
   getters: {
      
   },
   mudules: {

   }
})

Vue实例使用store对象(main.js)

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store, // Vue实例使用store对象
  components: { App },
  template: '<App/>'
})

创建两个组件, 分别使用Vuex中state定义的count对象: this.$store.state.count

<template>
  <div>
    <h3>------------------子组件-----------------</h3>
    <p>子组件使用Vuex中state定义的 count: {{$store.state.count}}</p>
  </div>
</template>

<script>
export default {
  name: 'ChildCmp'
}
</script>
<template>
  <div>
    <h3>------------------父组件-----------------</h3>
    <p>父组件使用Vuex中state定义的 count: {{$store.state.count}}</p>
    <child-cmp/>
  </div>
</template>

<script>
import ChildCmp from './childCmp'

export default {
  name: 'ParentCmp',
  components: {
     ChildCmp
  }
}
</script>

在这里插入图片描述


(三) vuex-state

state: Vuex存储的状态对象, Vuex 使用单一状态树, 用一个对象就包含了全部的应用层级状态, 即作为一个唯一数据源而存在, 也意味着, 每个应用将只会有一个store实例

// 在此定义的状态, 状态对象共享给各个组件
state: {
	counter: 1,
	...
}

mapState: 辅助函数, 在组件中将多个状态定义为计算属性, mapState() 函数返回值是个compute对象

  • mapState({}): 函数的参数为对象
    import { mapState } from 'vuex'
    
    export default {
    	... ,
    	
    	computed: mapState({
    		// 第一种写法: 计算属性名: function(state) { return ... }
    		counter1 : function(state) {
    			// state: Vuex中state对象
    			return state.counter * 10
    		}
    
    		// 第二种写法: 计算属性名: '字符串参数', 等同于 counter1: state => state.counter
    		counter1: 'counter'
    	})
    }
    
  • mapState([]): 函数的参数为数组
    import { mapState } from 'vuex'
    
    export default {
    	... ,
    	// 计算属性的名称 与 state中对象名称相同
    	computed: mapState([
    		'counter'
    	])
    }
    
  • mapState() 函数 与 组件内计算属性 并存(对象展开运算符)
    import { mapState } from 'vuex'
    
    export default {
    	... ,
    	data() {
    		return {
    			num: 10
    		}
    	},
    	computed: {
    		increment() {
    			return num+++
    		},
    		...mapState({})
    	}
    }
    

(三) vuex-getters

getters: 可以认为是store的计算属性, 对state状态对象进行逻辑计算, 且getters的返回值会根据它的依赖被缓存起来, 只有当它的依赖值发生改变才会被重新计算

export default new Vuex.store({
	state: {
		counter: 100
	},
	getters: {
		// 默认参数传递state对象和getters对象
		powerCounter(state, getters) {
			return state.counter * state.counter
		},
		sumCounter(state) {
			// 返回一个函数, 函数存在一个参数num, 函数再返回num+counter
			return function(num) {
				return state.counter + num
			}
		}
	}
})
<h3>{{$store.getters.powerCounter}}</h3> <!-- 10000 -->
<h3>{{$store.getters.sumCounter(100)}}</h3> <!-- 200 -->

(四) vuex-mutations

Mutation状态更新: 更改Vuex的store中的状态的唯一方法是提交mutation, 且 Mutation 必须是同步函数, 是为让devtools工具可以捕捉mutation的快照, 记录每一次对state的操作. 如果为异步操作, devtools工具无法记录

mutation主要包括两部分:

  • 字符串的事件类型(type)
  • 一个回调函数(handler), 函数有两个参数: state状态对象 和 payload载荷对象(commit提交时, 传入的额外参数对象)

通过 this.$store.commit(‘事件类型’, payload) 修改Vuex的store中的状态

export default new Vuex.store({
	state: {
		counter: 100
	},
	mutations: {
		// 事件类型: function(状态对象, 载荷参数) {}
		increment: function(state, payload) {
			state.counter += payload
		},
		encrement(state, payload) {
			state.counter -= payload.num // 因为下面使用了对象的提交风格
		}
	}
})
<template>
  <div>
    <p>{{$store.state.counter}}</p>
    <button @click="addition(5)">+5</button>
    <button @click="subtraction(10)">-10</button>
  </div>
</template>

<script>
export default {
	name: 'ParentCmp',
	methods: {
		addition(num) {
			// 通过提交mutation修改Vuex的store中的状态
        	this.$store.commit('increment', num)
	    },
	    subtraction(num) { 
	    	// 对象风格的提交方式
	    	this.$store.commit({
	    		type: 'encrement',
	    		num
	    	})
	    }
	}
}
</scritp>

在这里插入图片描述


(五) vuex-actions

Action: 类似于Mutation, 用来替代Mutation进行异步操作. Action最终还是只能通过提交mutation来修改状态, 而不是直接变更状态

action主要包括两部分:

  • 字符串的事件类型(type)
  • 一个回调函数(handler), 函数有两个参数: context状态对象 和 payload载荷对象(dispatch分发时, 传入的额外参数对象)

通过 this.$store.dispatch(‘事件类型’, payload) 分发Action

export default new Vuex.store({
	state: {
		counter: 100
	},
	mutations: {
		increment: function(state, payload) {
			state.counter += payload
		},
		encrement(state, payload) {
			state.counter -= payload.num 
		}
	},
	actions: {
		// 事件类型: function(状态对象, 载荷参数) {}
		asynincrement(context, payload) {
			// 模拟异步操作
			setTimeout(() => {
				// action 内部也是通过提交mutation来修改状态
				context.commit('increment', payload)
			}, 1000)
		}
	}
})
<template>
  <div>
    <p>{{$store.state.counter}}</p>
    <button @click="addition(5)">+5</button>
    <button @click="subtraction(10)">-10</button>
    <button @click="asynAddition(10)">异步 +10</button>
  </div>
</template>

<script>
export default {
	name: 'ParentCmp',
	methods: {
		addition(num) {
        	this.$store.commit('increment', num)
	    },
	    subtraction(num) { 
	    	this.$store.commit({
	    		type: 'encrement',
	    		num
	    	})
	    },
	    asynAddition(num) {
		    // 通过 this.$store.dispatch('事件类型', payload) 分发Action
	    	this.$store.dispatch('asynincrement', num)
	    }
	}
}

在这里插入图片描述

(六) vuex-modules

Vue使用单一状态树, 意味着只存在一个Store实例, 会将所有的状态对象交给一个Store来管理, 当应用变的非常复杂时, Store对象就会变得异常臃肿

Module: Vuex允许将Store分割成 module模块, 每个模块都拥有自己的 state、getters、mutations、actions等. 多个模块, 使用 namespaced命名空间属性来区分

const moduleA = {
	namespaced: true, // 使用命名空间属性来区分模块
	state: {
		name: 'zhangsan' // this.$store.state.moduleA.name 获取
	},
	gettters: {
		/*
			state:	当前模块state状态对象
			getters: 当前模块getters计算属性
			rootState: 根模块state状态对象(也包含了所有子模块state对象)
			rootGetters: 根模块rootGetters计算属性(也包含了所有子模块rootGetters计算属性)
		*/
		nameInfo(state, getters, rootState, rootGetters) {
			return sate.name + ' Info' // this.$store.getters['module/nameInfo'] 获取
		}
	},
	mutations: {
		updateNameM(state, payload) {
			state.name = 'lisi' // this.$store.commit('moduleA/updateNameM') 提交
		}
	},
	actions: {
		/*
			context: store上下文对象
			context: {state, getters, rootState, rootGetters, commit, dispatch}
		*/
		updateNameA(context, payload) {
			setTimeout(() => {
           		context.commit('updateNameM') // this.$store.dispatch('moduleA/updateNameA') 分发Action
         	}, 1000)
		}
	}
}

const moduleB = {
	namespaced: true,
	state: {...},
	getters: {...},
	mutations: {...},
	actions: {...},
	modules: {...}
}

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

使用辅助函数绑定带命名空间的模块

import {mapState, mapGetters, mapActions, mapMutations} from 'vuex'

export default {
	name: 'ParentCmp',
	computed() {
		...mapState('moduleA', [
			'name',
			...
		]),
		...mapGetters('moduleA', [
			'nameInfo',
			...
		])
	},
	method() {
		...mapMutations('moduleA', [
			'updateNameM',	// 直接当普通方法使用, 自动提交
			...
		]), 
		...mapActions('moduleA', [
			'updateNameA', // 直接当普通方法使用, 自动分发
			...
		])
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值