VueX状态管理
✍目录总览:
一、VueX概念
1. VueX的概念
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- VueX里面所有数据都可以全局使用。
2. 状态管理的概念
可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。
将这个对象放在顶层的Vue实例中,让其他组件可以使用。
二、单界面的状态管理
在单文件组件中进行状态管理:
图片中的三种东西如下:
- State:状态
- View:视图层,可以针对 State 的变化,显示不同的信息
- Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的变化
//单文件组件内部代码
<template>
<div>
<div>当前计数:{{counter}}</div>
<button @click="counter+=1">+1</button>
<button @click="counter-=1">-1</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
counter: 0
}
}
}
</script>
<style scoped>
</style>
上述案例中,需要管理的状态:个数counter。
-
counter需要某种方式被记录下来,也就是我们的State。
-
counter目前的值需要被显示在界面中,也就是我们的View部分。
-
界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions
三、多界面状态管理
3.1 单个文件的组件状态管理清晰明了,那多个单文件组件的状态管理呢?(出现的问题)
- 多个组件都依赖同一个状态(一个状态改了,多个组件界面需要进行更新)
- 不同界面的 组件Actions 都想修改同一个状态(Home.vue 需要修改,Profile.vue 也需要修改这个状态)
3.2 VueX背后的基本思想:(解决方法)
1. 将多个组件共享的状态抽取出来,交给我们的大管家VueX,统一进行管理。
2. 每个组件视图,按照VueX的规则定,进行访问和修改等操作。
四、VueX 基本用法
1. 安装VueX
- 方式1:通过命令行npm进行安装。
npm install vuex --save
- 方式2:Vue-cli3脚手架生成 Vue 项目基础架构时候,进行配置选择。
2. 使用步骤
我们创建一个文件夹 src/store,并且在其中创建一个 store.js 文件,代码如下:
import Vuex from 'vuex'
import Vue from 'vue'
// 1.安装插件
Vue.use(Vuex)
// 2.创建对象
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state){
state.count++
},
decrement(state){
state.count--
}
},
actions: {
},
getters: {
},
modules: {
}
})
// 导出store对象
export default store
其次,我们让所有的Vue组件都可以使用这个store对象
- 来到 src/main.js文件,导入store对象,并且挂载到new Vue中
import Vue from 'vue'
import App from './App'
// 1.导入store对象
import store from './store'
new Vue({
el: '#app',
// 2.挂载 store
store,
render: h => h(App)
})
- 这样,在其他Vue组件中,我们就可以通过
this.$store
的方式,获取到这个store对象了
//app.vue根组件
<template>
<div id="app">
<p>
<button @click="increment">+1</button>
<button @click="decrement">-1<</button>
</div>
</template>
//行为层
<script>
export default {
name: 'App',
components: {
},
computed: {
count: function() {
return this.$store.state.count
}
},
methods: {
increment: function() {
this.$store.commit('increment')
},
decrement: function() {
this.$store.commit('decrement')
}
}
}
</script>
使用步骤小结:
- 提取出一个公共的 store 对象,用于保存在多个组件中共享的状态
- 将 store 对象放置在 new Vue 对象中,这样可以保证在所有的组件中都可以使用到
- 在其他组件中使用 store 对象中保存的状态即可
- 通过 this.$store.state 属性的方式来访问状态
- 通过 this.$store.commit('mutation中方法') 来修改状态
- 我们通过提交 mutation 的方式,而非直接改变 store.state.count
- 这是因为 Vuex 可以更明确的追踪状态的变化,所以不要直接改变 store.state.count 的值
五、VueX核心概念🔥
🔥🔥🔥强调:VueX的store.js定义方式固定,获取方式有两种:
- $store 当作全局对象直接进行访问
- import 作为模块导入为组件内部属性或方法
1. State 单-状态树(共享变量)
State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 的 State 中进行存储。
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state: { count: 0 }
})
组件获取 State 中数据的第一种方式:
this.$store.state.全局数据名称
组件获取 State 中数据的第二种方式:
// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from 'vuex'
通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的 computed 计算属性:
// 2. 将全局数据,映射为当前组件的计算属性
computed: {
...mapState(['count'])
}
2. Mutation状态更新(函数修改变量)
- Mutation 用于变更 Store中 的数据。
① 只能通过 mutation 变更 Store 数据,不可以直接操作 Store 中的数据。
② 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。
2.1 Mutation用法🔥
调用方式一:
调用方式二:
2.2 Mutation传参🔥
调用方式一:
调用方式二:
1.store.js内定义函数
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//store.js内定义函数
export default new Vuex.Store({
state: {
count: 0
},
// 只有 mutations 中定义的函数,才有权利修改 state 中的数据
mutations: {
subN(state, step) {
state.count -= step
}
},
}
2.在组件文件内导入函数 绑定函数
//组件文件内导入函数 绑定函数
<template>
<div>
<h3>当前最新的count值为:{{count}}</h3>
//引入的函数进行绑定
<button @click="subN(3)">-N</button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
data() {
return {}
},
computed: {
//将指定的state变量,映射为当前组件的computed计算属性
...mapState(['count']),
},
methods: {
//将指定的 mutations 函数,映射为当前组件的 methods 函数
...mapMutations(['sub', 'subN']),
}
}
</script>
3. Action异步任务(异步函数调用mutation)
- Action 用于处理异步任务。
如果通过异步操作变更数据,必须通过 Action,而不能使用 Mutation,但是在 Action 中还是要通过触发Mutation 的调用方式间接变更数据。
3.1 Action用法🔥
调用方式一:
- actions 异步任务(不带参)
- 触发 actions 异步任务时携带参数:
3.2 Action传参🔥
调用方式二:
- actions 异步任务(不带参)
//store.js内定义函数
export default new Vuex.Store({
state: {
count: 0
},
// 只有 mutations 中定义的函数,才有权利修改 state 中的数据
mutations: {
sub(state) {
state.count--
}
actions: {
subAsync(context) {
setTimeout(() => {
context.commit('sub')
}, 1000)
}
//组件文件内导入函数 绑定函数
<template>
<div>
<h3>当前最新的count值为:{{count}}</h3>
//引入的函数进行绑定
<button @click="subAsync">-1 Async</button>
</div>
</template>
<script>
//导入store.js里面的acion、mutation函数,acion内部调用mutation
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
data() {
return {}
},
computed: {
//将指定的state变量,映射为当前组件的computed计算属性
...mapState(['count']),
},
methods: {
//将指定的 action 函数,映射为当前组件的 methods 函数
...mapMutations(['sub']),
...mapActions(['subAsync'])
}
}
</script>
- 触发 actions 异步任务时携带参数:
1.store.js内定义函数
2.在组件文件内导入函数 绑定函数
4. Getters基本使用(变量加工)
- Getter 用于对 Store 中的数据进行加工处理形成新的数据。
① Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
② Store 中数据发生变化,Getter 的数据也会跟着变化。
1.store.js内定义函数
2.调用VueX
调用方式1:当作全局对象直接进行调用
调用方式2:在组件文件内导入模块 绑定属性和函数
5. Module模块化
Module 是模块的意思,为什么在 Vuex 中我们要使用模块呢?
- Vue 使用单一状态树,那么也意味着很多状态都会交给 Vuex 来管理
- 当应用变得非常复杂时, store 对象就有可能变得相当臃肿
- 为了解决这个问题,Vuex 允许我们将 store 分割成某块,而每个模块拥有自己的 state、mutations、action、getters等
const ModuleA = {
state: {},
mutations: {},
actions: {},
getters: {}
}
const ModuleB = {
state: {},
mutations: {},
actions: {},
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态