Vuex 概述
官方文档:https://vuex.vuejs.org/zh/
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vue 应用中的每个组件在 data() 中封装着自己数据属性,而这些 data 属性都是私有的,完全隔离的。如果我们希望多个组件都能读取到同一状态数据属性,或者不同组件的行为需要更新同一状态数据属性,这就需要一个将共享的状态数据属性进行集中式的管理。这就是 Vuex 状态管理所要解决的问题。
简单使用
使用vue-cli创建一个项目,命名为vue-demo,安装依赖和运行
# 进入工程目录 cd vuex-demo # 安装依赖 npm install --save vuex # 运行项目 npm run serve
访问 http://localhost:8080/,正常访问就表示配置的没有问题
每一个 Vuex 项目的核心就是 store(仓库)。 store 就是一个对象,它包含着你的项目中大部分的状态(state)。
state 是 store 对象中的一个选项,是 Vuex 管理的状态对象(共享的数据属性)
在 src 目录下创建 store 目录,store 下创建 index.js 文件, 编码如下:
import Vue from 'vue' import Vuex from 'vuex' // 引用vuex插件 Vue.use(Vuex) const store = new Vuex.Store({ //注意V和S都是大写 // 存放状态(共享属性) state:{ count: 1 } }) export default store
修改 main.js,导入和注册 store,编码如下:
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");
组件中读取 state 状态数据,修改 src\views\Home.vue,编码如下:
<template> <div> count: {{ $store.state.count }} </div> </template> <script> </script>
访问 http://localhost:8080/ 页面显示如下
改变状态值 mutation
在 store 的 mutations 选项中定义方法,才可以改变状态值。在通过 $store.commit('mutationName') 触发状态值的改变
修改 store/index.js , 在 store 中添加 mutations 选项,编码如下:
import Vue from 'vue' import Vuex from 'vuex' // 引用vuex插件 Vue.use(Vuex) const store = new Vuex.Store({ //注意V和S都是大写 // 存放状态(共享属性) state:{ count: 1 }, // 改变state状态 mutations:{ // 加法 increment(state){ state.count++ }, // 减法 decrement(state){ state.count-- } } }) export default store
修改 src\views\Home.vue ,调用 mutations 中 increment、decrement 方法
<template> <div> count: {{ $store.state.count }} <button @click="addCount">加法</button> <button @click="decrement">减法</button> </div> </template> <script> export default{ methods: { addCount() { // 获取状态值 console.log(this.$store.state.count) // 通过commit 调用 mutations 中的 increment 改变状态值 this.$store.commit('increment') }, decrement() { console.log(this.$store.state.count) // 通过commit 调用 mutations 中的 decrement 改变状态值 this.$store.commit('decrement') } }, } </script>
点击 加法 按钮,控制台和页面显示数字变化
载荷
你可以向 $store.commit 传入额外的参数,即 mutation 的 载荷(payload):
修改 src\store 下的 index.js
...... // 改变state状态 mutations:{ increment(state, n){ // n 为载荷 state.count+=n // state.count=state.count+n }, decrement(state){ state.count-- } } })
修改 views\Home.vue 组件
<template> <div> count: {{ $store.state.count }} <button @click="addCount">加法</button> <button @click="decrement">减法</button> </div> </template> <script> export default{ methods: { addCount() { // 获取状态值 console.log(this.$store.state.count) // 通过commit 调用 mutations 中的 increment 改变状态值 this.$store.commit('increment',5) // 提交载荷 }, decrement() { console.log(this.$store.state.count) // 通过commit 调用 mutations 中的 decrement 改变状态值 this.$store.commit('decrement') } }, } </script>
页面上点击加法会一次加5,减法还是一个一个的减
Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是在组件中直接变更状态, 通过它间接更新 state。
- 在组件中通过 this.$store.dispatch('actionName') 触发状态值间接改变
- Action 也支持载荷
- Action 可以包含任意异步操作。
修改 store/index.js ,增加 actions 选项
import Vue from 'vue' import Vuex from 'vuex' // 引用vuex插件 Vue.use(Vuex) const store = new Vuex.Store({ //注意V和S都是大写 // 存放状态(共享属性) state:{ count: 1 }, // 改变state状态 mutations:{ increment(state, n){ // n 为载荷 state.count+=n // state.count=state.count+n }, decrement(state){ state.count-- } }, actions: { add(context, n) { // 触发 mutations 中的 increment 改变 state context.commit('increment', n) }, decrement({commit, state}) { // 按需传值 commit('decrement') } } }) export default store
修改 views\Home.vue, 触发 action 改变值
<template> <div> count: {{ $store.state.count }} <button @click="addCount">加法</button> <button @click="decrement">减法</button> </div> </template> <script> export default{ methods: { addCount() { // 获取状态值 console.log(this.$store.state.count) // 通过commit 调用 mutations 中的 increment 改变状态值 // this.$store.commit('increment') // this.$store.commit('increment', 10) // 提交载荷 // 触发 actions 中的 add 改变状态值 this.$store.dispatch('add', 10) }, decrement() { console.log(this.$store.state.count) // 通过commit 调用 mutations 中的 decrement 改变状态值 // this.$store.commit('decrement') this.$store.dispatch('decrement') } }, } </script>
派生属性 getter
有时候我们需要从 store 中的 state 中派生出一些状态。
例如:基于上面代码,增加一个 desc 属性,当 count 值小于 50,则 desc 值为 吃饭 ; 大于等于 50 小于100,则desc 值为 睡觉 ; 大于100 , 则 desc 值为 打豆豆 。这时我们就需要用到 getter 为我们解决。
getter 其实就类似于计算属性(get)的对象
组件中读取 $store.getters.xxx
修改 store\index.js ,增加 getters 选项
getters 中接受 state 作为其第一个参数,也可以接受其他 getter 作为第二个参数
import Vue from 'vue' import Vuex from 'vuex' // 引用vuex插件 Vue.use(Vuex) const store = new Vuex.Store({ //注意V和S都是大写 // 存放状态(共享属性) state:{ count: 1 }, // 改变state状态 mutations:{ increment(state, n){ // n 为载荷 state.count+=n // state.count=state.count+n }, decrement(state){ state.count-- } }, actions: { add(context, n) { // 触发 mutations 中的 increment 改变 state context.commit('increment', n) }, decrement({commit, state}) { // 按需传值 commit('decrement') } }, //派生属性 getters: { desc(state) { if(state.count < 50) { return '吃饭' }else if(state.count < 100) { return '睡觉' }else { return '打豆豆' } } } }) export default store
修改 views\Home.vue, 显示派生属性的值
<template> <div> count: {{ $store.state.count }} <button @click="addCount">加法</button> <button @click="decrement">减法</button> 派生属性desc: {{ $store.getters.desc }} </div> </template>
点击 Home 页面的 触发改变 按钮,当 count 新增到 51 , desc 是否会显示为 睡觉