vue之vuex

一. 介绍

1. 概念

Vuex是一个专为Vue.js应用程序开发的状态管理模式(状态管理工具).采用集中式存储管理应用的所有组件的状态,此昂已响应的规则保证状态以一种可预测的方式发生变化.

状态管理模式、集中式存储管理: 将把需要多个组件共享的变量存储到一个对象中,再将此对象放在顶层的Vue实例中,实现具有响应式的组件内容共享

通常使用Vuex进行信息共享的内容有: token, 用户信息等

二. 使用

1. 注册
  • vue2对应vuex3.x
// vuex的index.js
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
	// 属性名是固定的,不可修改
	// state存储需要共享的变量或状态
	state: {
		// 定义共享变量或属性
		name: 'xiaolin'
	},
	mutations: {
	},
	actions: {
	},
	modules: {
	}
})

export default store

// main.js
import Vue from 'vue'
import store from './store'

new Vue(
	el: '#app',
	store,
	// ...
)
  • vue3对应vuex4.x
// vuex的index.js
import {createStore} from 'vuex'

const store = createStore({
	// 见官方修改state中内容图解
	// component ----Dispatch----> Actions ----Commit----> Mutations ----Mutate----> State
	// 也支持直接通过Mutations修改,跳过Actions步骤
	// 属性名是固定的,不可修改
	// state存储需要共享的变量或状态
	state: {
		// 定义共享变量或属性
		name: 'xiaolin'
	},
	mutations: {
		// 定义修改state的内容的函数
	},
	actions: {
		// 定义行为,通常是在修改state中的内容的同时有异步操作时使用
		// 不建议在Mutation进行异步操作
	},
	modules: {
	}
})

export default store

// main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App).use(store).use(router).mount('#app')

注意:vue3的实例创建方式发生了变化,需要注意vue的版本和组件版本,在vue3中不支持Vue.vue(plugin),所以需要使用有createXxx函数的版本插件

2. 基本使用
  • 定义共享内容: 在注册vuex插件时,即可同时定义共享内容
  • 获取: 在任意插件中都可通过this.$store.state.xxx获取共享的内容
  • 修改: 通过mutations中定义函数修改state中定义的内容
mutations: {
	// mutation中定义的函数,参数会传定义的store中的state对象
	increment(state) {
		state.counter ++;
	}
}

调用方式:

this.$store.commit('increment')
3. Vuex的核心概念
  1. State: 单一状态定义状态,可以直接调用查看,不建议直接修改
  2. Getters: 类似计算属性,可以对State中定义的内容进行处理后返回
// 定义
getters: {
	// 基本使用
	powerCounter: state => {
		return state.counter * state.counter;
	},
	// getters中调用定义的getters
	thirdPowerCounter: (state, getters) => {
		return getters.powerCounter * state.counter
	},
	// getters中的参数是固定的,所以需要使用接受的参数时,可以返回一个函数,此时调用getters实际就是调用定义的函数,接收到的参数就是定义的函数的参数
	counterMoreNumber: (state, getters) => {
		return function(number) {
			return state.counter > number;
		}
	}
}
// 使用
// getters是当做属性来使用的,所以不需要"()"
this.$store.getters.powerCounter
// 当getters返回的是一个函数时,调用该getters就是调用该函数,需要添加"()","()"中的参数就是返回的函数中传入的参数
// 如下相当于 return state.counter > 3
this.$store.getters.counterMoreNumber(3);
  1. Mutation: 修改State中定义的状态(唯一方式),通常要求必须是同步函数

Mutation主要包括两部分:

mutations: {
	increment(state) { state.counter ++ ;}
}
  1. 字符串的事件类型(type),如上述的increment,通常会认为是函数名称;在通过mutation更新state时,commit函数的参数就是事件类型
  2. 一个回调函数(handler),该回调函数的第一个参数就是state,第二个参数是接受调用时传入的参数,如上述事件类型后面跟的函数,通常是函数体

mutation的定义和调用

  1. 参数被称为mutation的载荷(payload)
  2. 如果有多个参数,通常使用对象行使传递
提交方式

普通提交方式

mutations: {
	addStudent(state, payload) {
		// 普工提交方式的payload得到的就是参数对象
		state.students.push(payload);
	}
}
let student = {id: 1, name: 'xiaolin', age: 18}
// 此处调用时传入的student参数通常称为payload(负载)
this.$store.commit('assStudent', student)

包含type属性的对象提交方式

mutations: {
	addStudent(state, payload) {
		// 使用对象方式提交时,payload实际是整个mutation调用时的对象
		state.students.push(payload.stadent);
	}
}
let student = {id: 1, name: 'xiaolin', age: 18}
// 使用一下方式提交时,payload对象实际是整个参数对象{type: 'addStudent', student: {id: 1, name: 'xiaolin', age: 18}}
this.$store.commit({
	type: 'addStudent',
	student
})
响应规则

store中的state是响应式的,但必须遵守对应的规则

  1. 提前在store中初始化好所需的属性

  2. 当给state中的对象添加或删除属性时, 使用如下方式:

    -方式一:使用Vue.set(targetObj, 'key', value);Vue.delete(targetObj, 'key')
    -方式二: 用新对象给旧对象重新赋值
    注意: 在使用vuex4.x时,对应的vue版本生成Vue实例(即app)的方式改为使用createApp方法生成,而不是new,vuex也使用createStore方法生成store,所以Vue.set方法无法获取,在4.x版本中的官方文档中也将 Mutation 需遵守 Vue 的响应规则 这一节内容删除;作为代替,可以直接给state中的对象添加内容,如

mutations: {
		updateInfo(state) {
			state.info['age'] = 18
		}
}
mutations: {
	setField(state, payload) {
		Vue.set(state, payload.key, payload.student)
	}
}
this.$store.commit({
	type: 'setField',
	key: 'info',
	student
})
  1. Action: 处理(异步)操作
    Action类似Mutation,但允许异步操作
    一般使用方式
updateStuInfo(context, payload) {
	// 此处的context上下文就是store
	setTimeout(() => {
		context.commit('updateInfo')
	}, 1000)
}
let payload = {// ...}
this.$store.dispatch('updateStuInfo', payload)

返回提示信息的方式

updateStuInfo(context, payload) {
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			context.commit('updateInfo')
			resolve()
		}, 1000)
	})
}
let payload = {// ...}
this.$store.dispatch('updateStuInfo', payload).then(() => {
	// ...
})
  1. Module: 分模块,将store中的内容分割成模块(Module),每个模块拥有字节的state,mutations,actions,getters
const user = {
	namespaced: true,
	state: {
		name: 'xiaolin'
	},
	getters: { 
		// state 是当前模块的state
	    // getters 是当前模块的getters
	    // rootState 是根节点的state
	    getUserName(state, getters, rootState) {
	      return state.name + "好帅!"
	    }
	},
	mutations: {
		userMutation(state, mutations, rootState) {
			// ...
		}
	},
	actions: {
		userAction(state, actions, rootState) {
			// ...
		}
	}
}
modules: {
	user: user
}

使用

this.$store.state.user.name;
// getters, mutations, actions命名空间未定义时调用方式
this.$store.getters['getUserName']
this.$store.commit('userMutation')
this.$store.dispatch('userAction')
// getters, mutations, actions命名空间为true时调用方式
this.$store.getters['user/getUserName']
this.$store.commit('user/userMutation')
this.$store.dispatch('user/userAction')

三. 整体案例

定义

import { createStore } from 'vuex'
// 定义一个user模块
const user = {
	// 命名空间设为true和不设为true是有区别的
	// 主要是内容归属问题
	// 当为true时,则表示内容属于当前子项
	// 否则表示内容不区域无差别
  namespaced: true,
  state: () => ({
    name: 'xiaolin',
  }),
  getters: {
    // state 是当前模块的state
    // getters 是当前模块的getters
    // rootState 是根节点的state
    // getters和rootState名称可以换
    getUserName(state, getters, rootState) {
      console.log("state:", state);
      console.log("getters", getters);
      console.log("rootState", rootState);
      return state.name + "好帅!"
    },
  },
  mutations: {
    userMutation(state, payload) {
      console.log("state", state);
      console.log("payload", payload);
    }
  },
  actions: {
  	// context对象
    userAction(context) {
      console.log("state", context.state);
      console.log("commit", context.commit);
      console.log("rootState", context.rootState);
    }
  }

}

export default createStore({
  state: {
    counter: 0,
    info: {
      name: 'xiaolin',
      age: 18
    }
  },
  getters: {
    getInfo: state => {
      return state.info
    }
  },
  mutations: {
    increment(state) {
      state.counter++
    },
    updateInfo(state) {
      state.info['id'] = 1
    }
  },
  actions: {
    infoAction(state) {
      setTimeout(() => {
        console.log("infoAction");
      })
    }
  },
  modules: {
    user: user
  }
})

调用

console.log("info", this.$store.state.info);
console.log("-------------");
console.log("user.name", this.$store.state.user.name);
console.log("-------------");
this.$store.commit('increment')
console.log("-------------");
console.log("counter", this.$store.state.counter);
this.$store.getters['user/getUserName'];
console.log("-------------");
this.$store.commit('user/userMutation', 'payload);
console.log("-------------");
this.$store.dispatch('user/userAction');

结果
函数调用结果

函数调用结果
函数调用结果

函数调用结果

子模块的Action中的context参数的内容:
context参数
context参数

日 期 : 2021 − 12 − 01 \color{#00FF00}{日期:2021-12-01} 20211201

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值