vuex动态注册嵌套module提供模块内部组件间的数据共享
Posted 左直拳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vuex动态注册嵌套module提供模块内部组件间的数据共享相关的知识,希望对你有一定的参考价值。
vuex提供了全局性的共享数据。如果数据限于模块内共享,可以采用嵌套module,通过命名空间进行访问。
vue开发的主角是组件。组件在代码解耦、复用、提高可读性方面立下功劳,但组件间共享数据、传递参数却很麻烦,尤其是组件嵌套层次很深的情况。如果是祖宗辈传递参数给儿孙辈还好一些,祖宗provider,儿孙inject;然而这是单向的,儿孙想更改祖宗里的这些值就难了。因为你想用 this.$parent
,未必能找到父一辈的组件。就算能找到,this.$parent.$parent...
这种方式也让人抓狂。
vuex就是为了解决这个问题的。其工作方式,就是所有组件都能访问、更改vuex对象里的数据。数据是共用的,有组件改了,所有组件看到的都变了。就好像在操作一个全局变量一样。
这样就会有一个问题。由于vuex提供的是全局性的数据共享机制,它的作用域是整个系统,不存在说我只在子系统内声明一个vuex对象,自己访问就好。如果我没有理解错误的话,一个系统,有且只有一个vuex对象。如果工程比较复杂,存在多个子系统,所有共享数据都放在一个vuex对象里,会很拥挤和臃肿。因此vuex提供了module,每个module都是一个store对象,并且可以嵌套。这样可以将子系统、模块的共享数据,存储进vuex对象里的相应module,区分层次。同时,module可以采取动态注册的方式,即当运行子系统或模块的时候,才注册相关module;关闭或退出子系统和模块,注销module。以下是详细说明:
一、创建vuex对象
src/store/index.js,这是面向整个系统的
import Vue from 'vue'
import Vuex from 'vuex'
import user from './module/user'
import app from './module/app'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
//
},
mutations: {
//
},
actions: {
//
},
modules: {
user,
app
}
})
二、某模块的store module
某模块的store module(src/projects/dzzhyj/store.js)
const key = 'dzzhyj'
export default {
install (_this) {
if (_this.$store.state[key]) {//如果module已经存在,则先注销
$store.unregisterModule(key)
}
_this.$store.registerModule([key], {
/*
actions
1、用于通过提交mutation改变数据
2、会默认将自身封装为一个Promise
3、可以包含任意的异步操作
mutations
1、通过提交commit改变数据
2、只是一个单纯的函数
3、不要使用异步操作,异步操作会导致变量不能追踪
*/
namespaced: true,//请注意,是namespaced!而不是namespace!这个属性与类似“dzzhyj/product/”
modules: {
product: {
namespaced: true,
state: {
v: 'hello world', // for test
details: []
},
mutations: {// 同步操作
setV (state, val) {
state.v = val
},
setDetails (state, val) {
state.details = val
}
},
actions: {// 异步操作
getV ({ state }) {
return state.v
},
keepDetails: ({ commit }, val) => {
commit('setDetails', val)
}
}
}
}
})
},
uninstall (_this) {
_this.$store.unregisterModule([key])
}
}
三、动态注册store module
下图中,页签容器页、页签都是一个个独立的组件。在页签容器页(即明细信息对话框)注册,“报告”页签写入数据,“地图”页签读取数据。
在模块的明细信息对话框里进行注册store module(src/view/projects/dzzhyj/product/_pop.vue)
<!-- 这是一个弹出框 -->
<template>
<div>
<Modal v-model="modal1" :width="width" :styles="{ top: '10px' }" draggable >
。。。
</Modal>
</div>
</template>
<script>
import myStore from '@/projects/dzzhyj/store.js'
export default {
data () {
return {
...
}
},
created () {
myStore.install(this) //注册我的store module
},
destroyed () {
myStore.uninstall(this)//注销我的store module
},
methods: {
...
}
}
</script>
四、更改数据
src/view/projects/dzzhyj/product/_report.vue
<template>
<div class="page-container">
“报告”页签。。。
</div>
</template>
<script>
export default {
data () {
。。。
},
methods: {
keepDetails (val) {
//想支持这种 'dzzhyj/product/keepDetails' action,store中的namespaced = true
this.$store.dispatch('dzzhyj/product/keepDetails', val).then(() => {
console.log('已缓存明细数据')
})
}
}
}
</script>
五、读取数据
“报告”页签的兄弟页签“地图”读取明细数据进行绘制
src/view/projects/dzzhyj/product/_map.vue
<template>
<div class="map-container">
"地图"页签。。。
</div>
</template>
<script>
export default {
data () {
。。。
},
methods: {
dyeing (details) {
//地图绘制
}
},
computed: {
getDetails () {
let details = null
if (this.$store.state.dzzhyj && this.$store.state.dzzhyj.product) {
details = this.$store.state.dzzhyj.product.details
}
return details
}
},
watch: {
getDetails (val) {
this.dyeing(val)
}
}
}
</script>
六、总结
如果没有vuex,两个并列的页签组件之间,如何传递数据呢?可以将数据通过emit传给容器页,再由容器页传给另一个页签。比较麻烦,也不清晰。
vuex可以很好地解决组件间数据共享的问题。当然,如果明白vuex的原理,自己写代码实现一个store.js之类的组件也可以,但没有必要,就用vuex好了,很方便。之前见过网上一些文章都说,如果参数传递不太多,就没必要用这个vuex;甚至有人说不想用vuex。给人的感觉,就是vuex是个很庞大、笨重、复杂的东西。其实呢,vuex并不复杂,反而很好用,只是有一两个坑,避开就好。
以上是关于vuex动态注册嵌套module提供模块内部组件间的数据共享的主要内容,如果未能解决你的问题,请参考以下文章
Vuex:具有动态命名空间的 createNamespacedHelpers