说起vuex,vue开发人员必定使用过。我也用过,不过一直是copy-paste based developmement。后来开始接触graphql了,就很少再用vuex了,现在也基本淡忘了。今天回看了自己以前写的代码,vuex使用一团糟,胡学瞎用最后成了技术债。
组件化开发
现代主流的web应用基本上都是组件化开发的思路,下图是其中一个很常见的web组件架构:后端只提供单纯的数据读写服务,前端负责主要的业务流;后来,随着前端日益沉重,又从中分出了一个中间层管理缓存和数据状态(Cache & State)。Vuex就是这个中间层里管理状态的一个工具。
Vuex 的功能类似于总线,使用的是全局单例模式。下图是vuex模式下的单向数据流:
State:驱动应用的数据源;
View:以声明方式将 state 映射到视图;
Actions:响应在 view 上的用户输入导致的状态变化。
OK,我以前写代码的时候就看到上图,后来照着网上的demo胡搬滥造(捂脸),结果vue组件里到处都是如下代码片:
let logo = this.$store.state.company.info.logo;
this.$store.commit('company/info', info);
store之后的一堆field又臭又长,全文检索密密麻麻。后来起新项目的时候,我就几乎不再用vuex了。前段时间和组里的一个小朋友聊vuex的时候,他告诉我vuex是这样的(当时惊了……):
组件产生actions后,在store里commit mutations方法,mutations随之更新state,最后由Getter方法反映到组件里。一套很优雅的实现:状态的变化实现了高度统一管理。比起我当年的写法,代码变得更加简洁高效。(一百分)
Demo
简单写了个demo,用代码来反映一下上图所示的数据流。下图由两个组件构成:
Selected 所在行:用于显示vuex里的state
三个radio组成的选择面板:用于触发vuex action,从而更新state。
State
首先自建一个store.js,用来管理所有vuex state相关的数据以及操作。state
就是我们要管理的全局状态,它是一个任意指定的对象。
const state = {
radio: '',
};
const actions = { ... };
const mutations = { ... };
const getters = { ... };
export default new Vuex.Store({state, getters, mutations, actions});
Actions
Actions是一组对vue组件开放的api集合。现在的前端开发很少再在vue methonds里直接调用后端api了,更多的是通过这类action统一代理;当然,在vuex里它的主要工作还是commit mutations里的方法,比如这里的updateRadio
。
const actions = {
selectRadio ({commit}, val) {
commit('updateRadio', val);
},
};
Mutations
接着就是刚提到的mutations了。Mutations里也是一系列方法集,它的功用类似于vuex里的私有方法,由上一层actions触发,并直接修改state。
const mutations = {
updateRadio (state, val) {
state.radio = val;
}
};
Getter
最后一部分就是Getter集合,顾名思义,它的功用是对vue组件暴露state的特定状态。
const getters = {
getRadio () {
return state.radio;
}
}
Mapper
vuex的map方法是新版本里的一大亮点(学Redux的),也是我重学vuex后最大的收获:Store里的Actions和Getters通过解构(Destructuring assignment)赋值为methods
和computed
的方法。(对,就是那三个点)
<template>
<h1>Selected: {{ getRadio }}</h1>
<label v-for="o in ['Onion', 'Ginger', 'Garlic']">
<input @click="selectRadio($event.target.value)"
name='seasoning' type='radio' :value=o>
{{ o }}
</label>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
methods: {
...mapActions(['selectRadio']),
},
computed: {
...mapGetters(['getRadio']),
}
};
</script>
如上所示,我们可以在input
的点击事件里直接绑定action方法selectRadio
,并在该事件触发后通过getter方法的getRadio
展示state里radio的状态。
小结
可能是近来有点脱产了,vuex也没上心学习一下;要不是组里小朋友提醒,我可能都不愿意去碰它了。人不学,不知道,要时刻牢记技术是我等底层小职员安身立命的唯一选项。