Vuex是Vue全家桶的重要一员,日常使用中一般都是下面这种项目结构。
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
问题
现在我的项目模块比较多,而且大部分模块用到了Vuex,第一次打开网页单单Store所在的Chunk就有几百K,而且Store太臃肿对运行效率必定也会有所影响,实在不符合我追求高效简洁的理念。Vuex的API也提供了registerModule unregisterModule来动态注册和卸载模块,具体怎么使用呢?
方案level1
在模块对应页面组件的生命周期函数beforeCreate beforeDestroy里边调用API来注册写在就好喽。代码就是下边这样子。
import module from '@/src/store/module'
export default {
beforeCreate() {
if(!this.$store.hasModule('modulePath')) {
this.$store.registerModule('modulePath', module);
}
},
beforeDestroy() {
if(this.$store.hasModule('modulePath')) {
this.$store.unregisterModule('modulePath');
}
}
}
这样写太不严谨了,modulePath应该用个变量,另外好多模块都动态加载的话一个一个写太费劲了吧。OK,再改进一下。
方案level2
// 这里写个mixin
export default function(path, module) {
return {
beforeCreate() {
if (!this.$store.hasModule(path)) {
this.$store.registerModule(path, module);
}
},
beforeDestroy() {
if (this.$store.hasModule(path)) {
this.$store.unregisterModule(path);
}
}
};
}
// 组件里边使用mixin
import mixin from './mixin'
import module from '@/src/store/module'
export default {
mixins: [mixin("modulePath", module)]
}
其实可以用动态导入,传递模块的地址和
namespace两个参数就好,但是webpack打包时仍然会将动态路径下所有文件打包在一起,也就没有代码分割了,所以还是要单独导入。
这样挺不错了,每个组件顶多也就多写三行代码。但是不太对啊,万一我两个组件用一个模块,关了一个组件,就卸载了,我另一个组件怎么用?这个问题好说,mixin里边写个map放上每个模块的引用组件,beforeCreate里边添加引用,同时注册模块,beforeDestroy里边删除引用,如果没有引用就卸载模块。
方案level3
// 不想写了
还有一个问题,我一个组件用多个模块怎么办?这个问题简单,多import几个就好了,
方案level4
import mixin from './mixin'
import module1 from '@/src/store/module1'
import module2 from '@/src/store/module2'
import module3 from '@/src/store/module3'
export default {
mixins: [mixin("modulePath1", module1), mixin("modulePath2", module2), mixin("modulePath3", module3)]
}
这里不太科学,mixin应该可以支持数组的,我就不写了。
这就有点烦了,一个个import下来累坏我。后期还要手动维护更改。
方案level5(终极方案)
下面介绍一下我的lazy-store-loader,不要import,不要mixin,只要配一下webpack.config.js就行了!!!当然夸张了,还要手动维护一个映射对象。
{
"modulePath": "@/src/module"
}
就是注册模块时模块的namespace和文件路径的映射。mixin和import会在编译时通过loader注入,同时也会维护每个模块和组件之间的引用,防止提前卸载模块,同时防止了卸载静态注册的模块时引发异常(搞自己项目时踩的坑)内部原理其实和上边的思路差不多,注入的过程是通过解析<script>中的mapActions mapMutations mapState获取使用到的模块,通过映射文件获取到路径,然后注入相关代码。
项目地址
github.com/YinDongFang… 各位大佬感兴趣记得点个star
如果再懒点其实可以直接源码搞到自己项目,映射文件也不用,直接统一用namespace做路径