vuex

152 阅读5分钟

我们可以使用vuex来保存我们需要管理的状态值,值一旦被修改,所有引用该值的地方就会自动更新。

新建项目

// 安装vuecli脚手架:
npm install -g @vue/cli-init

// 使用webpack创建一个项目名web:
vue init webpack web
cd web

// 启动项目:
npm run dev

// 安装vuex保存到本地:
npm install vuex --save

目录结构

然后我们在项目的src目录下新建一个目录store

在该目录下新建一个index.js文件,我们用来创建vuex实例,然后在该文件中引入vue和vuex,创建Vuex.Store实例保存到变量store中,最后使用export default导出store:

// store -> index.js

import Vue from 'vue'
import Vuex from 'vuex'

// 使用vuex
Vue.use(Vuex)

// 创建vuex实例
const store = new Vuex.Store({

})
// 导出store
export default store

然后我们在main.js文件中引入该文件

// main.js

// 在文件里面添加 import store from ‘./store’
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

// 再在vue实例全局引入store对象
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

然后我们就可以开始编写我们的vuex业务代码了,那么,我们的数据如何保存?

State

vuex中的数据源,我们需要保存的数据就保存在这里,可以在页面通过 this.$store.state 来获取我们定义的数据;

index.js

image

HelloWorld.vue文件修改如图

image

这时候我们页面上就得到了这个count值1

image

Getters

Getter相当于vue中的computed计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,这里我们可以通过定义vuex的Getter来获取,Getters 可以用于监听、state中的值的变化,返回计算后的结果。

index.js修改

image

index.js文件中,其中getters中的getStateCount方法接收一个参数state,这个参数就是我们用来保存数据的那个对象;

HelloWorld.vue文件修改如图

image

这时候我们页面显示

image

Mutation

官网解释:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

所以,数据我们在页面是获取到了,但是如果我们需要修改count值怎么办?如果需要修改store中的值唯一的方法就是提交mutation来修改

修改index.js文件,添加mutations,在mutations中定义两个函数,用来对count加1和减1

image

修改HelloWorld.vue文件添加两个按钮,一个加1,一个减1

这里我们点击按钮调用 addFn(执行加的方法)和 reductionFn(执行减法的方法),然后在里面直接提交mutations中的方法修改值:

image

页面效果

image

Actions

官网解释:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation
  • Action 通过 store.dispatch 方法触发

所以页面上的值是改变了;我们达到了修改store中状态值的目的。

但是, 官方并不介意我们这样直接去修改store里面的值,而是让我们去提交一个actions,在actions中提交mutation再去修改状态值。

接下来我们修改index.js文件,先定义actions中提交mutation的函数:

image

修改HelloWorld.vue文件如下:

image

这里我们把commit提交mutations修改为使用dispatch来提交actions;我们点击页面,效果是一样的。

页面效果

image

如果我们需要指定加减的数值,那么我们直接传入dispatch中的第二个参数,然后在actions中的对应函数中接受参数在传递给mutations中的函数进行计算:

image

image

页面效果

image

好了,我们这里已经实现了一个基本的vuex修改状态值的完整流程。

但是但是每次this.stroe.state.countthis.store.dispatch这种写法代码很长,也不太受欢迎,怎么办呢?

那么有没有其他的办法呢?别慌,当然有了,我们可以使用mapState、mapGetters、mapMutations、mapActions就不会这么麻烦了

辅助函数

mapState

修改HelloWorld.vue文件如下:

image

页面效果如下

image

效果一模一样

mapGetters

修改HelloWorld.vue文件如下

image

image

效果还是一样

mapMutations

image

mapActions

image

效果

image

总结

借用官方的话来说:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

优缺点

vuex的优点:

  1. js 原生的数据对象写法, 比起 localStorage 不需要做转换, 使用方便
  2. 属于 vue 生态一环,能够触发响应式的渲染页面更新(localStorage 就不会)
  3. 限定了一种可预测的方式改变数据, 避免大项目中, 数据不小心的污染

vuex的缺点:

  1. 刷新浏览器,vuex中的state会重新变为初始状态
  2. 解决方案-插件vuex-persistedstate

插件 vuex-persistedstate

插件的原理其实也是结合了存储方式,只是统一的配置就不需要手动每次都写存储方法。

安装

npm install vuex-persistedstate --save

引入及配置:在store下的index.js

import createPersistedState from "vuex-persistedstate"

const store = newVuex.Store({
  // ...
  plugins: [createPersistedState()],
});

默认存储到localStorage

想要存储到sessionStorage,配置如下

import createPersistedState from "vuex-persistedstate"
 
const store = newVuex.Store({
  // ...
  plugins: [
    createPersistedState({
      storage: window.sessionStorage,
    }),
  ],
});

默认持久化所有state

指定需要持久化的state,配置如下

import createPersistedState from "vuex-persistedstate"

conststore = newVuex.Store({
  // ...
  plugins: [
    createPersistedState({
      storage: window.sessionStorage,
      reducer(val) {
        return {
          // 只储存state中的assessmentData
          assessmentData: val.assessmentData,
        };
      },
    }),
  ],
});

vuex引用多个插件的写法

譬如:vuex提示的插件和持久化的插件一起使用,配置如下

import createPersistedState from "vuex-persistedstate"
import createLogger from 'vuex/dist/logger'
// 判断环境 vuex提示生产环境中不使用

const debug = process.env.NODE_ENV !== 'production'
 
const createPersisted = createPersistedState({
  storage:window.sessionStorage
})
 
export default newVuex.Store({
  // ...
  plugins: debug ? [createLogger(), createPersisted] : [createPersisted]
})

plugins要是一个一维数组不然会解析错误