使用 vuex-pathify 驯服 Vuex 野兽
就 Flux 架构实现而言,Vue.js 的 Vuex 是最简单但最优雅的实现之一。但是,它仍然可以做得更好。试图记住为商店中的每个属性编写 getter 和突变似乎有点不必要的认知开销。为什么我们需要手动映射 getter、突变和操作?Dave Stewart的commit
“和dispatch
again”之间有什么区别?试图通过为 Vuex 功能提供简单的包装器并依靠惯例来减少样板来减少所有这些脑力开销。vuex-pathify
本文假设您有一个已设置 Vuex 的 Vue.js 项目,并且您了解其工作原理的基本知识。如果没有,请查看我们的Vuex 指南。
安装 vuex-pathify
首先,继续安装 pathify 并在基本 Vuex 存储配置中将其作为插件启用。
$ npm install --save vuex-pathify
然后在您的商店中启用该插件。
import Vue from 'vue';
import Vuex from 'vuex';
// If you want to configure pathify, this import will be different.
// See the "Configuring Pathify" section below.
import pathify from 'vuex-pathify';
import App from './App.vue';
Vue.use(Vuex);
// Usual Vuex stuff. Normally not in the main file.
const state = {};
const getters = {};
const mutations = {};
const actions = {};
const actions = {};
const store = new Vuex.Store({
// Enable the vuex-pathify plugin.
plugins: [pathify.plugin],
state,
getters,
mutations,
actions,
modules,
});
new Vue({
store,
render: h => h(App)
}).$mount('#app');
比较
所以现在的问题是......做什么vuex-pathify
?
普通 vuex
为了说明这一点,我们来看看基本的 Vuex 设置。只需一个很小的表单,您就可以使用双向数据绑定编辑您的名字和姓氏。
import Vue from 'vue';
import Vuex from 'vuex';
import App from './App.vue';
Vue.use(Vuex);
const state = {
firstName: 'Richard',
lastName: 'Gator'
};
// We need these to be able to access
// their values outside of the store module.
const getters = {
firstName: state => state.firstName,
lastName: state => state.lastName
};
// We use these to update the values of the store.
const mutations = {
SET_FIRST_NAME: (state, firstName) => {
state.firstName = firstName
},
SET_LAST_NAME: (state, lastName) => {
state.lastName = lastName
}
};
const store = new Vuex.Store({
state,
getters,
mutations
});
Vue.config.productionTip = false;
new Vue({
store,
render: h => h(App)
}).$mount('#app');
<template>
<div id="app">
<h2>Your Name Is: {{firstName}} {{lastName}}</h2>
<form>
<label>
First Name
<input type="text" v-model="firstName"/>
</label>
<label>
Last Name
<input type="text" v-model="lastName"/>
</label>
</form>
</div>
</template>
<script>
export default {
name: 'app',
computed: {
// We have to create computed getters and setters for both properties
// to be able to use them in v-model.
// Quite a pain for larger forms, wouldn't you say?
firstName: {
get() { return this.$store.getters.firstName },
set(val) { this.$store.commit('SET_FIRST_NAME', val) }
},
lastName: {
get() { return this.$store.getters.lastName },
set(val) { this.$store.commit('SET_LAST_NAME', val) }
}
}
}
</script>
这么简单的事情,竟然需要这么多样板代码。您必须创建状态,添加 getter、突变和计算属性,以将它们全部绑定在一起。
使用 vuex-pathify
让我们看看同样的事情vuex-pathify
。
import Vue from 'vue';
import Vuex from 'vuex';
import pathify from 'vuex-pathify';
import { make } from 'vuex-pathify';
import App from './App.vue';
Vue.use(Vuex);
const state = {
firstName: 'Richard',
lastName: 'Gator'
};
// You don't even need getters, pathify will use the store data directly!
// Though if you want, it can generate them for you with `make.getters(state)`
// Same for mutations and actions. (Uses the SET_* format, but this is configurable.)
const mutations = make.mutations(state);
const store = new Vuex.Store({
// Don't forget the plugin!
plugins: [pathify.plugin],
state,
mutations
});
Vue.config.productionTip = false;
new Vue({
store,
render: h => h(App)
}).$mount('#app');
<template>
<div id="app">
<h2>Your Name Is: {{firstName}} {{lastName}}</h2>
<form>
<label>
First Name
<input type="text" v-model="firstName"/>
</label>
<label>
Last Name
<input type="text" v-model="lastName"/>
</label>
</form>
</div>
</template>
<script>
import { sync } from 'vuex-pathify';
export default {
name: 'app',
computed: {
// The sync helper creates two-way bindings for store data and mutations.
firstName: sync('firstName'),
lastName: sync('lastName'),
// We could reduce boilerplate even further using:
// ...sync(['firstName', 'lastName'])
}
}
</script>
对我来说这看起来冗余代码显著减少了!
机制
其核心vuex-pathify
是路径系统和解析算法。路径看起来是这样的:module/property@nested.sub.property
例如,对于此路径:data/user/firstName
,pathify 可以确定:
- 引用的模块是
user
该模块的子模块data
。 - getter 应该是
data/user/firstName
。 - 相关突变将是
data/user/SET_FIRST_NAME
。 - 相关行动将是
data/user/setFirstName
。
如果您要,pathify 将首先在模块的子模块pathify.get('data/user/firstName')
中查找 getter 。如果失败,它将直接引用商店中的属性。user
data
firstName
data.user.firstName
如果您要调用pathify.set('data/user/firstName', 'Richard')
,Pathify 将首先检查setFirstName
相关模块中的操作。如果不存在,它将检查SET_FIRST_NAME
突变并改用该突变。
pathify.sync('data/user/firstName')
允许您将这两种行为组合成一个计算属性。您可以使用语法@
来访问更多子属性。例如,如果您没有模块user
,但模块上有一个userData
属性data
,则可以使用pathify.sync('data/userData@firstName')
,效果相同。
这使得您可以使用Vuex
一致且简单的语法访问所有功能,而不必诉诸commit()
、dispatch()
等。
有关如何使用的详细信息vuex-pathify
,请参阅官方文档。
配置 Vuex-Pathify
如果您还没有开始使用,上述信息应该足以引起您的兴趣vuex-pathify
,但有一件事您应该注意。配置模块的方式与通常的方式略有不同。不是使用传递给构造函数的选项,而是在运行时vuex-pathify
通过修改原型上的属性进行配置。配置插件的推荐方式如下:
pathify.js
在源目录中创建一个名为 的新文件。- 导入pathify并修改配置值。
- 重新导出 pathify 并在您的
vuex
模块中使用它。
您可以修改的选项的完整列表可在此处找到。
// Import pathify.
import pathify from 'vuex-pathify';
// Mapping: /thing -> getter: thing, mutation: SET_THING, action: setThing
options.mapping = 'standard'; // Default
// Re-export pathify.
export default pathify;
...
import pathify from './pathify'; // instead of from `vuex-pathify.
...