文章目录
Vuex是什么
介绍:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
采用集中式存储管理应用中的所有组件的状态,适用于中大型项目的的开发
为什么使用vuex
由于Vue是单向数据流,组件之间的通讯都是依靠子传父,父传子,或者建立一个空的vue实例从而进行兄弟之间的传参,随着中大型项目的开发,组件越来越多,传统的传参模式显得太过于繁琐,于是vuex为此而来
Vuex的工作流程
官方给了一张超级完美的流程图。↓
vuex最繁琐的工作流程通过此图分析也显得非常易懂。列如:
组件想要修改state,通过this. s t o r e . d i s p a t c h ( " a c t i o n s 中 的 方 法 名 " ) 调 用 a c t i o n s 中 的 方 法 , 在 a c t i o n s 中 通 过 t h i s . store.dispatch("actions中的方法名")调用actions中的方法,在actions中通过this. store.dispatch("actions中的方法名")调用actions中的方法,在actions中通过this.store.commit(“mutations中的方法名”)调用mutations中的方法,在mutations中修改state中的数据,state中的数据发生改变就会立即响应到组件上
vuex使用之前的配置
- 安装vueX↓
cnpm install vuex -S
注:
-S 是–save的简写,意为:把插件安装到dependencies(生产环境依赖)中
-D是–save-dev的简写,意为:把插件安装到devDependencies(开发环境依赖)中
- 完整的vuex代码片段↓(在src中创建store文件夹,并在其内创建index.js)↓
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
- 在main.js(vue项目的入口文件)中进行引入,并放到vue的实例中↓
import store from './store' //index.js可无需写入,vue会自动读取文件夹内的index.js文件
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
vuex的核心概念
vue官方给出的是每一个 Vuex 应用的核心就是 store(仓库)。
但是在store中衍发出来了五大核心概念,即state、mutations、actions、getters、modules。
state(单一状态树—状态
)
state是vueX存放数据的地方
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。因此我们通常把state中的数据放到computed(计算属性)中,然后返回
- 在state中定义vueX中的数据↓
state: {
count:100,
price:25
}
- 在计算属性中进行获取并返回
每当 this.$store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM↓
computed: {
count () {
return this.$store.state.count
}
}
- 将计算属性中返回的数据放在template模板中↓
<p>{
{count}}</p>
也可以通过这种方式进行渲染state(不推荐)↓
<p>{
{$store.state.count}}</p>
这样我们就将vuex中的数据渲染到模板上了
mutations(状态更新—事件
)
mutations是唯一能操作state中数据的地方,mutations中默认的第一个参数是state,后面的数据都是我们需要传递的参数
- 在组件中通过
this.$store.commit('mutations中的事件名',参数)
调用mutations中的方法↓
plus(){
this.$store.commit("ADD",2)
}
- 最终在mutations中进行操作↓
mutations: {
ADD(state,val){
state.count+=val
}
}
actions(异步)
作用:是用来代替Mutation进行异步操作的
- 在组件中通过
this.$store.dispatch("actions中的方法名",参数)
来调用actions中的方法↓
plus(){
this.$store.dispatch("GOADD",5)
}
- 在actions中调用mutations中的方法(actions中默认的第一个参数指向store(这个参数有两种代替方式1.context 2.{commit}),其后皆是我们需要传递的形参)
- 方案一 ↓
GOADD(store,val){
store.commit("ADD",val)
}
- 方案二↓
GOADD(context,val){
context.commit("ADD",val)
}
- 方案三↓
GOADD({
commit},val){
commit("ADD",val)
}
- 在mutations中进行更改state数据
ADD(state,val){
state.count+=val
}
getters(计算)
该方法类似于computed(计算属性),可以将state中的数据做进一步的处理
- 在getters中将state中的进行计算↓
sum(state){
return state.count * state.price
}
- 在computed中将getters进行返回↓
sum(){
return this.$store.getters.sum
}
- 在模板中进行渲染↓
<p>{
{sum}}</p>
此方式依旧不推荐↓
<p>{
{$store.getters.sum}}</p>
modules(模块)
使用前提:当我们的项目在vuex中使用了过多的数据,从而会导致代码体积太过于庞大,不利于维护
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。
- 创建modules模块↓
const modulesA={
state:{
count:1000
},
actions:{
},
getters:{
},
mutations:{
ADD(state){
state.count++
}
}
}
const modulesB={
state:{
},
actions:{
},
getters:{
},
mutations:{
}
}
export default new Vuex.Store({
modules: {
MA:modulesA,
MB:modulesB
}
})
- 在组件中进行调用mudules模块中的state数据,依旧在computed中对数据进行一波返回,以及调用
MA
模块中的mutations中的方法↓
//computed计算属性中
number(){
return this.$store.state.MA.count //获取MA模块中state里面的count数据
}
//methods方法模块中
add(){
this.$store.commit("ADD") //调用MA模块中mutations里面的ADD方法
}
总结:
this.$store.state.'模块名'.'此模块state中的数据名'
,MA
模块中的getters
:“俺也一样”
this.$store.commit("模块中mutations中的方法名")
,MA
模块中的actions
:“俺也一样”
ES6模块化
此方法,个人觉得更利于维护和开发,更能大幅度降低单个js(store文件夹下面的index.js)文件的代码量,使代码看起来不是那么的臃肿。
- 方法如下↓
在store文件夹内创建state.js、mutations.js、getters.js、actions.js文件,在index.js文件中进行引入
列:state.js中的内容,其他js文件:“俺也一样”↓
const state={
count:1000
}
export default state
列:index.js↓
import Vue from 'vue'
import Vuex from 'vuex'
import state from "./state"
import mutations form "./mutations"
import actions form "./actions"
import getters form "./getters"
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules:{
//TODO
}
})
上方state是state:state的简写,es6规定属性名和属性值名字相同,可简写为单个名字
文件虽然多了,但是单个js文件的代码量少了,如果你们觉得可还行,可以参考哦^ (#^ . ^#) ^
当然也可以结合vueX中的modules一起使用
且看以下代码,亲测有效(在store文件夹内创建一个modulesA.js,并导出)↓
index.js代码↓
import Vue from 'vue'
import Vuex from 'vuex'
import ModulesA from "./modulesA"
Vue.use(Vuex)
export default new Vuex.Store({
modules:{
MA:ModulesA
}
})
modulesA.js代码↓
import state from "./state"
const modulesA={
state
}
export default modulesA**
state.js代码↓
const state={
count:1000
}
export default state
到此vueX的内置核心都已说完了,接下来上甜品↓看下方标题
vueX中的辅助函数
vueX中的语法糖
mapState
,mapActions
,mapMutations
,mapGetters
当一个组件需要多个状态时,这些状态都声明成计算属性过于冗长。于是有了辅助函数。
<template>
<div class="home">
<p>{
{
num}}</p>
<button @click="ADD">加一</button>
</div>
</template>
<script>
//导入vueX中mapState、mapMutations、mapGetters、mapActions的语法糖
import {
mapState,mapMutations,mapGetters,mapActions} from "vuex"
export default {
name: 'Home',
computed:{
...mapState({
num:'count'}),//也可以写成数组的形式,num是自定义名字,如若不自定义,可以写成数组的形式,参考mapMutations。
...mapGetters()
},
methods:{
...mapMutations(["ADD"]),//在模板的按钮中可以直接调用mutations中的方法。
...mapActions()
}
}
</script>
辅助函数结合模块一起使用
- 在模块中要开启命名空间
let moduleA = {
namespaced: true, //开启命名空间。
state: {
},
actions: {
},
mutations: {
},
getters: {
}
}
const store = new Vuex.Store({
modules: {
moduleA
},
- 在组件中引入vuex中的
createNamespacedHelpers
(命名空间辅助函数),拿到此函数内引入的模块名字,然后就可以愉快的使用了。在里面也可以进行重命名哦。
列如:当我们在此组件用到了vuex中公共的数据,同时也用到了模块中的数据,我们就可以用重新命名解决
<template>
<div id="app">
{
{
count}}
<button @click="add">点击</button>
</div>
</template>
<script>
import {
createNamespacedHelpers} from 'vuex' //引入命名空间辅助函数
const {
mapState:mapStateModuleA,mapActions:mapActionModuleA,mapMutations:mapMutationModuleA,mapGetters:mapGetterModuleA} = createNamespacedHelpers('moduleA')
export default {
methods:{
...mapActionModuleA(),
...mapMutationModuleA({
add:'ADD'})
},
computed:{
...mapStateModuleA(['count']),
...mapGetterModuleA()
}
}
</script>
呼!简单很多了吧,vuex这几个语法糖确实惊艳到我了,真的少了很多代码量。nice!
vueX数据持久化
有时候我们刷新页面,vuex的数据会变成初始化时候的数据,所以我们就需要保存vuex中的state里面的数据的状态,从而刷新页面,数据依然在。
- 安装
vuex-persistedstate
插件
npm install vuex-persistedstate -S
- 进行如下配置
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
state,
mutations,
actions,
getters,
plugins: [createPersistedState({
storage: sessionStorage,
key: "token"
})]//会自动保存创建的状态。刷新还在
})
storage:存储方式。(
sessionStorage
,localStarage
) key:定义本地存储中的key