6、Vuex 状态管理
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
6.1、初始 Vuex
6.1.1、什么是 Vuex
Vuex 是 Vue 团队提供的一套组件状态管理维护的解决方案。
vuex 作为 Vue 插件来使用,进一步完善了 Vue 基础代码功能,使 Vue 组件状态更加容易维护,为大型项目发开提供了强大的技术支持。
const store = new Vue.Store({
state: {},
mutaitons: {}
})
var vm = new Vue({
el: '#app',
store
})
6.1.2、Vuex 的下载和安装
Vuex 通常有两种安装方式,一种是直接通过
6.1.2.1、vuex.js 单文件引用
<script src="./vue.js"></script>
<script src="./vuex.js"></script>
<div id="root">
{{$store.state.name}}---{{name}}
</div>
<script>
const store = new Vuex.Store({
state:{
name: 'vuex.js 直接引用'
},
mutations: {
}
})
var mapState = Vuex.mapState
var vm = new Vue({
el: '#root',
data: {
// name: '潘嘉龙'
},
computed:mapState({
// 箭头函数可使代码更简短
name: state => state.name
}),
store
})
</script>
6.1.2.2、npm 导入 vuex 包
在使用 webpack 进行 Vue 开发时,vue 和 vuex 都是通过 npm 安装的。
命令安装 vuex:
npm install vuex@3.1.1 --save
创建 src/store/index.js 文件,用来导出 store 实例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
name: '正在使用 Vuex'
}
})
修改 src\main.js 文件,在 Vue 实例中注册 store 实例
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import vueRouter from 'vue-router'
Vue.use(vueRouter)
import router from './router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store,
router
}).$mount('#app')
修改 App.vue 文件
<template>
<div id="app">
<p>{{name}}</p>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default{
name: 'App',
computed : mapState({
name: state => state.name
})
}
</script>
6.1.4、Vuex 状态管理模式
Vue 中的单向数据流主要包含以下 3个 部分。
- State:驱动应用的数据源。
- View:以声明方式将 state 映射到视图。
- Actions:响应在 View 上的用户输入导致的状态变化。
6.2、Vuex 配置选项
6.2.1、actions
actions 选项用来定义事件处理方法,用于处理 state 数据。
actions 类似于 mutations,不同之处在于 actions 是异步执行的,事件处理函数可以接收 {commit} 对象,完成 mutation提交,从而方便 devtools 调试工具跟踪状态的 state 变化。
<div id="root">
<button @click="mut">查看 mutitions 接收的参数</button>
<button @click="act">查看 actions 接收的参数</button>
</div>
<script>
const store = new Vuex.Store({
state:{
name: '张三',
age: "38",
gender: "男"
},
mutations:{
test(state){
console.log(state);
},
},
actions:{
test(context, param){
console.log(param);
}
}
})
var vm = new Vue({
el: '#root',
data: {
name: '潘嘉龙'
},
store,
methods: {
mut(){
this.$store.commit('test');
},
act(){
this.$store.dispatch({type:'test', name:'我是传递的参数'});
}
},
})
</script>
6.2.2、mutations
mutations 选项中的事件处理方法接收 state 对象作为参数,即初始数据,使用时只需要在 state 实例配置对象中定义 state 即可。
mutations 中的方法用来进行 state 数据操作,在组件中完成 mutations 提交就可以完成组件状态更新。
<div id="root">
<button @click="param">传递参数</button>
<p>{{$store.state.param}}</p>
</div>
<script>
const store = new Vuex.Store({
state: { param :''} ,
mutations: {
receive(state, param){
debugger
console.log(param); // 查看接收到的param值
state.param = param.name
}
},
actions: {
param({commit}){
// commit('receive', '我是传递的参数')
commit({type:'receive', name:'我是传递的参数'})
}
}
})
var vm = new Vue({
el: '#root',
store,
methods: {
param(){
this.$store.dispatch('param')
}
},
data: {
name: '潘嘉龙'
}
})
</script>
6.2.3、getters
store 实例允许在 store 中定义 getters 计算属性,类似于 Vue 实例的 computed。
getters 返回值会根据它的依赖进行处理然后缓存起来,且只有当它的依赖值发生改变时才会被重新计算。
<div id="root">
<p>{{$store.getters}}</p>
<p>{{$store.getters.doneTodosCount}}</p>
</div>
<script>
const store = new Vuex.Store({
state:{
todos:[{
id:1, text:'我已完成',done:true,
},{id:2, text:'我没有完成',done:false,}]
},
getters:{
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
})
var vm = new Vue({
store,
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
6.2.4、modules
modules 用来在 store 实例中定义模块对象。
<div id='root'>
</div>
<script>
const moduleA = {
state: {nameA: 'A'}
},
const moduleB = {
state: {nameB: 'B'}
}
const store = new Vuex.Store({
modules:{
a: moduleA,
b: moduleB,
}
})
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
6.2.5、plugins
Vuex 中的插件配置选项为 plugins,插件本身为函数。
函数接收参数 store 对象作为参数。
store 实例对象的 subscibe 函数可以用来处理 mutation,函数接收参数为 mutation 和 state。
<div id='root'>
</div>
<script>
const myPlugin = store => {
// 当store初始化后调用
store.subscribe((mutation,state) => {
// 每次 mutation 提交后调用,mutation 格式为{type,payload}
console.log(mutation.type, mutation.payload);
})
}
const store = new Vuex.Store({
mutations:{
do(state){
console.log(state);
}
},
plugins:[myPlugin],
state:{
name: '潘金莲'
}
})
store.commit('do', 'plugin')
new Vue({
el: '#root',
store,
data: {
name: '潘嘉龙'
}
})
</script>
6.2.6、devtools
store 实例配置中的 devtools 选项用来设置是否在 devtools 调试工具中启用 Vuex,默认值为 true,表示在启用,设为 false 表示停止使用。
devtools 选项经常用在一个页面中存在多个 store 实例的情况。
<div id='root'>
</div>
<script>
const store = new Vuex.Store({
mutations: {
do(state){
console.log(state);
}
},
// devtools 选项
// devtools: false,
})
store.commit('do', 'plugin')
new Vue({
el: '#root',
store,
data: {
name: '潘嘉龙'
}
})
</script>
6.3、Vuex 中的 API
Vuex.Store() 构造器创建的 store 对象提供了一些 API,可以进行模块注册、状态替换等,从而能高效地进行项目开发。
6.3.1、模块注册
Vuex 提供了模块化开发思想,主要是通过 modules 选项完成注册。
这种方式只能在 store 实例对象中进行配置,显得不灵活。
store 实例对象提供了动态创建模块的接口,即 store.registerModule() 方法。
<div id='root'>
</div>
<script>
const store = new Vuex.Store({
})
// 方法接收模块名称 “myModule” 作为第一个参数,接收配置对象作为第二个参数
store.registerModule('myModule', {
state: {
name: '我是 store.registerModule() 定义的模块'
}
})
document.write(store.state.myModule.name)
new Vue({
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
如果已经创建成功的模块不再使用,可以通过 store.unregisterModule(‘moduleName’) 来动态卸载模块,但不能使用此方法卸载静态模块。
6.3.2、状态替换
state 数据状态操作,可以通过 store.replaceState() 方法实现状态替换。
该方法接收新的 state 对象,用来在组件中展示新对象的状态。
<div id='root'>
<p>{{$store.state.name}}</p>
</div>
<script>
const store = new Vuex.Store({
state: {
name: 'name初始值'
}
})
store.replaceState({name: '我是替换后的 state 数据'})
new Vue({
el: '#root',
store,
data: {
name: '潘嘉龙'
}
})
</script>