Vuex 注册:
// main.js 中导入 store,并在 Vue 中注册
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Vuex 配置:
// store 文件下 index.js 文件进行 vuex 的配置:
import Vue from 'vue'
import Vuex from 'vuex'// 导入 Vuex 对象
Vue.use(Vuex)// 调用 vuex 的 install 方法
// store 是一个构造函数,接受五个属性为参数
export default new Vuex.Store({
// 状态管理仓库,将需要统一管理的状态存储到 state 中
state: {},
// Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
getters: {},
// 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
mutations: {},
// Action 提交的是 mutation,而不是直接变更状态; Action 可以包含任意异步操作
actions: {},
// Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
modules: {},
})
简而言之:vuex 中有五个属性进行状态管理,
- state 用于统一储存 需要管理的状态;
- getters 相当于 vue 的computed,监听状态变化执行响应操作;
- mutations 更改状态的同步操作;
- actions 更改状态的异步操作,最终提交 mutations;
- modules 可以简单理解为分模块状态管理,模块中具备 vuex 的所有功能;
Vuex 基本使用:
mapState , mapGetters , mapMutations 辅助函数:简化使用 $store.state…
- state
// store 文件下 index.js
export default new Vuex.Store({
state: {
count: 0,
msg: "hello VueX"
}
})
// ---------- state 使用 -----------
// 1. $store.state.count
// 2. 简化使用:可直接使用 count
import { mapState } from "vuex"
export default {
//strict:true,// 严格模式开启,只是抛出异常,生产环境不建议开启严格模式,会深度检查状态树影响性能
strict: process.env.NODE_ENV !== "production",
computed: {
// mapState 会返回一个对象,包含两个计算属性对应的方法如下:
// {count: state => state.count,..}
// mapState 的参数可以接收数组,也可以接收对象
// ...mapState(['count','msg'])
// 如果 data 中已存在 count msg 设置属性名
...mapState({ num: 'count', message: 'msg' })
}
}
- getters
// store 文件下 index.js
export default new Vuex.Store({
state: {
count: 0,
msg: "hello VueX"
},
// getter 相当于组件的计算属性,对state的数据进行处理再展示
getters: {
reverseMsg(state) {
return state.msg.split('').reverse().join('')
}
}
})
// ---------- getters 使用 -----------
// 1. $store.getters.reverseMsg
// 2. 简化使用:可直接使用 reverseMsg
import { mapGetters } from "vuex";
export default {
computed: {
// mapGetters 会返回一个对象,包含两个计算属性对应的方法如下:
// count: state => state.count
// ...mapGetters(['reverseMsg','...'])
// 如果 data 中已存在 reverseMsg 设置属性名
...mapGetters({ msg: 'reverseMsg', '...': '...' })
}
}
- mutations
// store 文件下 index.js
// 视图中修改状态 mutation
export default new Vuex.Store({
// 点击按钮增加数值
mutation: {
// state 状态
// payload 额外参数,可为对象
increate(state, payload) {
state.count += payload
}
}
})
// ---------- mutation 使用 ----------- devtools 中方便调试
// mutation 本质是方法,使用时需要commit方法提交,使用 map 函数将 mutation 映射到当前组建的 mes 中
// 每次点击按钮,count 值加一
// 1. @click = "$store.commit('increate',1)"
// 2. 简化使用:可直接使用 @click = "inc(1)"
// mapMutations 返回一个对象,对应 mutation 中的方法,不再是计算属性,需要放到 methods 中
import { mapMutations } from "vuex";
export default {
methods: {
...mapMutations({ inc: 'increate', '...': '...' })
}
}
- actions
// store 文件下 index.js
// 执行异步状态 actions
export default new Vuex.Store({
actions: {
// context 第一个参数:包含state commit getters 成员
increateAsync(context, payload) {
setTimeout(() => {
// 提交到 mutations
context.commit('increate', payload)
}, 2000)
}
}
})
// ---------- action 使用 -----------
// 1. @click = "$store.dispatch.('increateAsync',1)"
// 2. 简化使用:可直接使用 @click = "inc(1)"
// mapActions 返回一个对象,对应 Actions 中的方法,不再是计算属性,需要放到 methods 中
import { mapActions } from "vuex";
export default {
methods: {
...mapActions({ inc: 'increateAsync', '...': '...' })
}
}
- modles
// 导入 vuex 的模块,模块的内容与主模块相同
import cart from "./module/cart";
import products from "./module/products";
export default new Vuex.Store({
modules: {
cart,
products
}
})
// ---------- modules 使用 -----------
// 1. @click = "$store.commit('setNums',[])
// 2. cart 存储在 $store.state 中,调用使用 $store.state.cart... 调用;mutation 调用如上
// 3. 命名空间:如 modules 中的 mutation 的方法与 state 中 mutation 的方法重名
import { mapState } from "vuex"
export default {
computed: {
...mapState(['setCart']),// 主模块中管理的状态 setCart
...mapState("cart", ["setCart"]) // cart 中管理的状态 setCart
},
methods: {
...mapMutations("cart", { setc: 'setCart', '...': '...' })
}
模拟简易 vuex
组件中的使用:我们将只实现以下 4 个属性功能
<template>
<div id="app">
<h1>Vuex - Demo</h1>
<h2>State</h2>
count:{{ $store.state.count }} <br>msg: {{ $store.state.msg }}
<h2>Getter</h2> {{ $store.getters.reverseMsg }}
<h2>Mutation</h2>// 修改状态调用$store.commit
<button @click="$store.commit('increate', 2)">Mutation</button>
<h2>Action</h2>// 执行异步操作调用 $store.dispatch 分发action
<button @click="$store.dispatch('increateAsync', 5)">Action</button>
</div>
</template>
根据配置我们知道 Vuex 返回一个对象:
- 使用 Vue.use() 调用 Vuex 的 install 方法,
- Vuex 中包含 Store 构造函数,接受 5 个属性为参数
import Vuex from 'vuex' // 导入 Vuex 对象
Vue.use(Vuex) // 调用 vuex 的 install 方法
export default new Vuex.Store({}) // store 是一个构造函数,接受五个属性为参数
vuex 基本结构:
// 在install 我们可以获取到 vue 的构造函数,后面我们还会在 store 使用到 vue 的构造函数,所以提前定义 _Vue
let _Vue = null
// 定义 Store 类
class Store {}
// 所有的插件都有一个 install 方法,vuex 的install 方法将 Store 挂载到 vue.$store 上
// install 需要接受两个参数 一个Vue 一个额外的选项,因为我们模拟的是简易的 Vuex 所以只接受 Vue 参数
function install (Vue) {
_Vue = Vue
}
// 导出内容
export default {
Store,
install
}
install 实现:
function install (Vue) {
_Vue = Vue
_Vue.mixin({ // 将 Store 注入 vue 实例,使 Store 在所有组件中可以通过 $store 访问
beforeCreate () {
// this 是 vue 实例,如果是组件实例则没有 store 对象
if (this.$options.store) {
_Vue.prototype.$store = this.$options.store
}
}
})
}
Store 类实现:
class Store {
// Store 接受 5 个属性参数
constructor(options){
const {
state = {}, // 设置默认值{},防止用户未传入该属性时报错
getters = {},
mutations = {},
actions = {}
} = options // 参数中的属性结构
// state
this.state = _Vue.observable(state) // 将state属性设置响应式数据
// getters
this.getters = Object.create(null)
Object.keys(getters).forEach(key => {
// 创建 getters 对象,遍历对象属性,利用 definedProperty 将 key 注册到 this.getters 对象中
Object.defineProperty(this.getters, keys, {
get: () => getters[key](state)
})
})
// 将 mutations,actions 存储到对应的属性中,在 commit ,dispatch 中要获取
this._mutations = mutations
this._actions = actions
}
// commit 方法
commit( type, payload){
this._mutations[type](this.state, payload)
}
diapatch( type, payload){
this._actions[type](this, payload)
}
}
总结:
- state:利用 vue 的 observable 将 state 中的状态设置为响应式数据
- getters:利用 Object.defineProperty() 将 getters 中定义的方法挂载到 store 上,传入 state 并执行响应方法
- mutations,action :则是通过 commit 与 dispatch 方法,进行调用内部方法