目录

前言

正文

一、基本概念

二、项目场景

三、如何使用

1、安装

2、State 初始值

3、Getters 修饰值

4、Mutations 修改值

5、Actions 异步修改值

四、总结

五、建议

何时使用 Vuex ?


前言

本人曾对 Vuex 作过详细介绍,但是今天去回顾的时候发现文章思路有些繁琐,不容易找到重点。于是,在下班前几分钟,我对其重新梳理了一遍。

tips:本文的案例均为Vue2版本。

正文

一、基本概念

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

二、项目场景

如果你的项目里有很多页面(组件/视图),页面之间存在多级的嵌套关系,此时,如果这些页面都需要共享一个状态的时候,此时就会产生以下两个问题:

  • 多个视图依赖同一个状态

  • 来自不同视图的行为需要变更同一个状态

解决方案(初版):

  • 对于第一个问题,假如是多级嵌套关系,你可以使用父子组件传参进行解决,虽有些麻烦,但好在可以解决;对于兄弟组件或者关系更复杂组件之间,虽然可以通过各种各样的办法解决,可实在很不优雅,而且等项目做大了,代码量愈发巨大,实在令人心烦。

  • 对于第二个问题,你可以通过父子组件直接引用,或者通过事件来变更或者同步状态的多份拷贝,但是这种模式很脆弱,使得代码难以维护,而且同样会让代码量剧增。

思路:

  • 把各个组件都需要依赖的同一个状态抽取出来,全局统一管理。

  • 在这种模式下,任何组件都可以直接访问到这个状态,或者当状态发生改变时,所有的组件都相应更新。

此时,Vuex 就诞生了。 这就是它背后的基本思想,借鉴了 Flux、Redux。与其他模式不同的是,Vuex 是专门为 Vue 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。

三、如何使用

1、安装

进入项目,键入以下命令:

npm install vuex --save

2、State 初始值

在 src 路径下创建 store 文件夹,并在该文件夹下新增 index.js 文件:

import Vue from 'vue';
import Vuex from 'vuex';Vue.use(Vuex);const store = new Vuex.Store({state: {// 定义一个name,以供全局使用name: 'leo'}
});export default store;

修改 main.js:

import Vue from 'vue';
import App from './App';
import store from './store';   // 引入我们前面导出的store对象Vue.config.productionTip = false;new Vue({el: '#app',store,   // 把store对象添加到vue实例上components: { App },template: '<App/>'
});

最后修改 App.vue:

<template><div></div>
</template><script>export default {mounted() {// 使用this.$store.state.xxx可以直接访问到仓库中的状态console.log(this.$store.state.name);   // 'leo'}}
</script>

建议一:this.$store.state.xxx 放在计算属性中,这样可以让你的代码看起来更优雅一些。

export default {mounted() {console.log(this.getName);   // 'leo'},computed:{getName() {return this.$store.state.name;}}
}

建议二:每次都写 this.$store.state.xxx 让你感到厌烦,造成代码冗余,可以使用 mapState。

<script>
import { mapState } from 'vuex';   // 从vuex中导入mapState
export default {mounted() {console.log(this.name);   // 'leo'},computed: {...mapState(['name'])   // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它}
}
</script>

你甚至可以给它取别名:

...mapState({ userName: 'name' })   // 赋别名的话,这里接收对象,而不是数组

3、Getters 修饰值

设想一个场景,你已经将 store 中的 name 展示到页面上了,而且是很多页面都展示了,此时客户要求在每个 name 前都加上“hello”。

最容易想到的办法就是去每个用到 name 的页面一个一个加上“hello”,显然这种方式并不友好,原因如下:

  • 第一,假如你在A、B、C三个页面都用到了 name,那么你要在这A、B、C三个页面都修改一遍,多个页面你就要加很多遍这个方法,造成代码冗余,很不好。

  • 第二,假如下次客户让你把“hello”改成“greet”的时候,你又得把三个页面(甚至更多)都改一遍,这时候你是拿石头砸自己的脚。

吸取上面的教训,我们有一个新的思路:直接在 store 中对 name 进行一些操作或者加工,从源头解决问题!这时候,Getter 闪亮登场!

首先,在 store 对象中增加 getters 属性:

const store = new Vuex.Store({state: {name: 'leo'},// 在store对象中增加getters属性getters: {getMessage(state) {   // 获取修饰后的name,第一个参数state为必要参数,必须写在形参上return `hello ${state.name}`;}}
});

在组件中使用:

export default {mounted() {console.log(this.$store.state.name);console.log(this.$store.getters.getMessage);   // 注意不是$store.state了,而是$store.getters}
}

建议使用 mapGetters:

<script>
import { mapState, mapGetters } from 'vuex';
export default {mounted() {console.log(this.name);   // 'leo'console.log(this.getMessage);   // 'hello leo' },computed: {...mapState(['name']),...mapGetters(['getMessage'])},
}
</script>

你也可以给它取别名:

...mapGetters({ greetMsg: 'getMessage' })   // 赋别名的话,这里接收对象,而不是数组

4、Mutations 修改值

说到修改值,有的人可能会想到这样写:

this.$store.state.xxx = XXX;

首先,这是一种错误的写法。为什么说是错误的写法?因为这个 store 仓库比较奇怪,你可以随便拿,但是你不能随便改,举个例子:

假如你打开朋友圈,看到你的好友发了条动态,但是动态里有个错别字,你要怎么办呢?你可以帮他改掉吗?当然不可以!我们只能通知他本人去修改,因为是别人的朋友圈,你是无权操作的,只有他自己才能操作。同理,在 Vuex 中,我们不能直接修改仓库里的值,必须用 Vuex 自带的方法去修改。这个时候,Mutation 闪亮登场!

首先,修改 store/index.js:

const store = new Vuex.Store({state: {name: 'leo',number: 0,},mutations: {   // 增加nutations属性setNumber(state) {   // 增加一个mutations的方法,方法的作用是让number从0变成5,state是必须默认参数state.number = 5;}}
});

然后,修改 App.vue:

<script>
export default {mounted() {console.log(this.$store.state.number);   // 旧值,0this.$store.commit('setNumber');console.log(this.$store.state.number);   // 新值,5},
}
</script>

如果我们想传动态参数怎么办?

首先,修改 store/index.js:

const store = new Vuex.Store({state: {name: 'leo',number: 0,},mutations: {setNumber(state, num) {   // 增加一个带参数的mutations方法state.number = num;},},
});

相应地,修改 App.vue:

<script>
export default {mounted() {console.log(this.$store.state.number);   // 旧值,0this.$store.commit('setNumber', 666);console.log(this.$store.state.number);   // 新值,666},
}
</script>

上面的这种传参的方式虽然可以达到目的,但是并不推荐。建议传递一个对象,看起来更美观,对象的名字你可以随意命名,一般命名为 payload:

mutations: {setNumber(state, payload) {   // 增加一个带参数的mutations方法,并且官方建议payload为一个对象state.number = payload.number;},
},

相应地,修改 App.vue:

<script>
export default {mounted() {console.log(this.$store.state.number);   // 旧值,0this.$store.commit('setNumber', { number: 666 });  // 调用的时候需要传递一个对象console.log(this.$store.state.number);   // 新值,666},
}
</script>

建议使用 mapMutations:

<script>
import { mapMutations } from 'vuex';
export default {mounted() {this.setNumber({ number: 666 });},methods: {   // 注意,mapMutations是解构到methods里面的,而不是计算属性了...mapMutations(['setNumber'])}
}
</script>

你也可以给它取别名:

methods:{...mapMutations({ changeNumber: 'setNumber' })   // 赋别名的话,这里接收对象,而不是数组
}

注意:Mutations 里面的函数必须是同步操作,不能包含异步操作。

Mutations 只能进行同步操作,所以,我们马上开始下一节,看看使用 Actions 进行异步操作的时候应该注意什么!

5、Actions 异步修改值

Vuex 不希望你将异步操作放在 Mutations 中,所以就给你设置了一个区域,让你进行异步操作,这就是 Actions。

首先,修改 store/index.js:

const store = new Vuex.Store({state: {name: 'leo',number: 0,},mutations: {setNumber(state, payload) {state.number = payload.number;},},actions: {   // 增加actions属性setNum(content) {   // 增加setNum方法,默认第一个参数是content,其值是复制的一份storereturn new Promise(resolve => {  // 模拟异步操作,1秒后修改number为666setTimeout(() => {content.commit('setNumber', { number: 666 });resolve();}, 1000);});}}
});

然后,修改 App.vue:

async mounted() {console.log(this.$store.state.number);   // 旧值,0await this.$store.dispatch('setNum');   // 等待异步操作完成console.log(this.$store.state.number);   // 新值,666
}

其实 action 就是去提交 mutation 的。异步操作都在 action 中消化了,最后再去提交 mutation。

当然,你也可以进行动态传参。

首先,修改 store/index.js:

actions: {setNum(content, payload) {   // 增加payload参数return new Promise(resolve => {setTimeout(() => {content.commit('setNumber', { number: payload.number });resolve();}, 1000);});},
}

相应地,修改 App.vue:

async mounted() {console.log(this.$store.state.number);   // 旧值,0await this.$store.dispatch('setNum', { number: 888 });console.log(this.$store.state.number);   // 新值,888
}

建议使用 mapActions:

<script>
import { mapActions } from 'vuex';
export default {methods: {...mapActions(['setNum']),   // 解构到methods中},async mounted() {await this.setNum({ number: 888 });  // 直接调用即可}
}
</script>

你也可以给它取别名:

...mapActions({ changeNumber: 'setNum' })   // 赋别名的话,这里接收对象,而不是数组

tips:在 actions 里面,方法的形参可以直接将 commit 解构出来,方便后续操作。

actions: {setNum({ commit }) {   // 直接将content结构掉,解构出commit,下面就可以直接调用了return new Promise(resolve => {setTimeout(() => {commit('xxx');  // 直接调用resolve();}, 1000);});},
},

四、总结

下班前这几分钟,你知道了如何使用 Vuex。你会安装它,配置它,读取 state 的值,甚至修饰读(Getters),然后你会修改里面的值(Mutations),如果有异步操作并且需要修改 state,那你就要使用 Actions。

一张神奇的图。

五、建议

何时使用 Vuex ?

这个问题因人而异,如果你不需要开发大型的单页应用,此时你完全没有必要使用 Vuex,比如你的页面就两三个,使用 Vuex 后增加的文件比你现在的页面还要多,完全没这个必要。

假如你的项目达到了中大型应用的规模,此时你很可能会考虑如何更好地在组件外部对状态进行统一管理,甚至会分模块(Vuex 中的 module,不展开),它将会是一个不错的选择。

下班前几分钟,我学会了如何使用 Vuex相关推荐

  1. 下班前几分钟,我彻底弄懂了 undefined 和 null 的区别

    目录 前言 一.基本概念 1.undefined 2.null 二.简单区别 三.表现形式 1.typeof 2.== 与 === 3.Object.prototype.toString.call 4 ...

  2. 下班前几分钟,逮到一个腾讯10年老测试开发,聊过之后彻底悟了...

    优秀的人真的是比比皆是,不比不知道,一比吓一跳 老话说的好,这人呐,一单在某个领域鲜有敌手了,就会闲得蛋疼.就在昨天下班的前几分钟认识了一个在阿里工作了 10 年的测试开发,因为本人天赋比较高,平时工 ...

  3. 下班前几分钟,我彻底弄懂了并查集

    目录 一.并查集的由来 二.代表元法 2.1 初始化 2.2 查询 2.3 合并 2.4 设计理念 三.并查集的应用 3.1 合并集合 3.2 连通块中点的数量 3.3 亲戚 3.4 省份数量 Ref ...

  4. 下班前10分钟光速安装skywalking并解决报错

    看标题就知道我当时慌的一批 下载方式 可以从官网下载apache-skywalking-apm-$version.tar.gz包.在windows或linux下都可以解压,因为运行参数需要指定里面的j ...

  5. 趁着下班前五分钟书写——Vue3通讯(常规写法、语法糖、v-modle、兄弟通讯)

    回顾  前期   [科技与狠活]-- JS实现页面阻塞三秒_0.活在风浪里的博客-CSDN博客_js实现阻塞while 循环 及 do while 的使用, 利用循环实现伪暂停进程 n 秒https: ...

  6. 只要5分钟!学会自己打造多系统合集的DVD安装光盘

    只要5分钟!学会自己打造多系统合集的DVD安装光盘(Windows All In One DVD ) 一.准备工作--需要软件 1. UltraISO(软碟通) v8.1.2.1625 下载:[url ...

  7. 快速学完计算机网络,如何让电脑网速变快 5分钟就学会

    如何让电脑网速变快 5分钟就学会 电脑有时候网速太卡,许多人都会想把电脑拿扔了.但是小编今天教你怎么让网速变快.首先在电脑上选择开始后在选择运行,如下图 如何让电脑网速变快 5分钟就学会 第二:输入: ...

  8. pythonturtle简单绘图_10分钟轻松学会 Python turtle 绘图

    10分钟轻松学会 Python turtle 绘图 python2.6版本中后引入的一个简单的绘图工具,叫做海龟绘图(Turtle Graphics),turtle库是python的内部库,使用导入即 ...

  9. 一分钟学会看k线图_一分钟怎样学会看k线图(纯干货)散户必备!

    原标题:一分钟怎样学会看k线图(纯干货)散户必备! K线图最早是日本德川幕府时代大阪的米商用来记录当时一天.一周或一月中米价涨跌行情的图示法,后被引入股市.K线图有直观.立体感强.携带信息量大的特点, ...

最新文章

  1. 那些在学习iOS开发前就应该知道的事(part 1)
  2. 算法笔记之回溯法(2)
  3. elasticsearch搜素关键字自动补全(suggest)
  4. python 读取excel太慢_Python 读取excel并转换为字典
  5. java修改默认字符编码_设置默认的Java字符编码?
  6. 漫步最优化四十四——基本拟牛顿法
  7. NET-由于该控件目前不可见、未启用或类型不允许,因此无法将焦点移向
  8. [Oracle] SQL*Loader 详细使用教程(3)- 控制文件
  9. 怎么在条码打印软件中修改数据库连接
  10. vim 的配置详解/键盘映射配置详解
  11. 路由器硬改+刷OpenWrt+挂载摄像头+U盘
  12. java 图片深度_图像的色彩值称为图像的颜色深度,黑白图像的颜色深度为( )位。...
  13. 利用函数wavread对语音信号进行采样_信号时间采样
  14. Web安全——同源策略理解
  15. 密立根油滴实验的c语言程序,密立根油滴实验数据处理程序c++
  16. 8.2 JVM命令行监控——jstat
  17. 关于Java线程,看这一篇就绝对够用了
  18. table隐藏列与colgroup标签
  19. cmd 添加端口映射
  20. 阅读《A2-RL: Aesthetics Aware Reinforcement Learning for Image Cropping Debang》

热门文章

  1. 超高清壁纸|文件收集
  2. html5 css3 渐变,CSS3 渐变 — 径向渐变
  3. RapidScada 应用---安卓手机端监控插件KpAndroid
  4. 2019 年最好用的 6 款数据库监控工具
  5. 从高考到程序员---一个五年程序员的回忆及建议
  6. 11、在屏幕上显示文本
  7. 【MySQL8入门到精通】基础篇-Windows安装及卸载MySQL
  8. php code coverage,PHP code coverage QuickStart
  9. Spring事务管理(转载自佚名大神)
  10. V4L 简介及其与V4L2区别