为动态创建的组件分隔vuex存储 [英] Separating vuex stores for dynamically created components
问题描述
这个问题让我陷入了一点困境。不幸的是,我在这里找不到答案(要求也没有帮助)。所以经过一些研究并在这里和那里询问后,似乎我得到了这个问题的解决方案。
This was the question got me stuck for a little bit. Unfortunately, I coudn't find answer here (asking also didn't help). So after doing some research and asking here and there, it seems that I got the solution to this issue.
如果您有一个问题,您已经知道了答案,并且您想要在公共场合记录这些知识,那么其他人
(包括你自己)可以在以后找到它。
If you have a question that you already know the answer to, and you would like to document that knowledge in public so that others (including yourself) can find it later.
当然,我的答案可能不是理想的,而且我知道它不是,这是我发布的关键点 - 改进它。
Of course, my answer may not be the ideal one, moreover I know it is not, that's the key point why I'm posting - to improve it.
注意,我没有在示例中使用动作。这个想法是一样的。
Note, I'm not using actions in example. The idea is the same.
让我们先从开始说明问题:
想象一下,我们有 App.vue
,它动态生成名为 Hello
的本地组件。
Imagine we have App.vue
which dynamically generates its local component named Hello
.
<template>
<div id="app">
<div>
<hello v-for="i in jobs" :key="i" :id="i"></hello>
<button @click="addJob">New</button>
</div>
</div>
</template>
<script>
import Hello from './components/Hello'
export default {
components: {
Hello
}...
store.js
store.js
export const store = new Vuex.Store({
state: {
jobs: []
}
})
我们正在使用 v-for
通过遍历数组生成组件的指令 jobs
。我们的商店
截至目前只包含一个空数组的州
。
按钮新
应该做两件事:
We are using v-for
directive to generate components by iterating through an array jobs
. Our store
as of now consists of only state
with an empty array.
Button New
should do 2 things:
1)创建新的组件 Hello
,换句话说,将元素添加到 jobs
(让它成为数字),这些将被指定为键
和 id
< hello>
,并通过本地组件为道具
。
1) create new component Hello
, in other words add element to jobs
(let it be numbers), which are going to be assigned as key
and id
of <hello>
, and passed to local component as props
.
2)生成本地商店 - 模块 - 保持任何数据作用于新创建的组件。
2) generate local stores - modules - to keep any data scoped to newly created components.
Hello.vue
Hello.vue
<template>
<div>
<input type="number" :value="count">
<button @click="updateCountPlus">+1</button>
</div>
</template>
export default {
props: ['id']
}
简单组件 - 输入一个按钮添加1.
Simple component - input with a button adding 1.
我们的目标是设计如下:
Our goal is to design something like this:
推荐答案
对于 NEW
按钮的第一次操作 - 生成组件 - 我们将变种
添加到我们的 store.js
For the first operation of NEW
button - generating components - we add mutation
to our store.js
mutations: {
addJob (state) {
state.jobs.push(state.jobs.length + 1)
...
}
其次,创建本地模块。在这里,我们将使用 reusableModule
来生成模块的多个实例。该模块我们保存在单独的文件中以方便。另外,注意使用函数来声明模块状态。
Second, creating local modules. Here we're going to use reusableModule
to generated multiple instances of a module. That module we keep in separate file for convinience. Also, note use of function for declaring module state.
const state = () => {
return {
count: 0
}
}
const getters = {
count: (state) => state.count
}
const mutations = {
updateCountPlus (state) {
state.count++
}
}
export default {
state,
getters,
mutations
}
要使用 reusableModule
,我们会导入它并应用动态模块注册。
To use reusableModule
we import it and apply dynamic module registration.
store.js
store.js
import module from './reusableModule'
const {state: stateModule, getters, mutations} = module
export const store = new Vuex.Store({
state: {
jobs: []
},
mutations: {
addJob (state) {
state.jobs.push(state.jobs.length + 1)
store.registerModule(`module${state.jobs.length}`, {
state: stateModule,
getters,
mutations,
namespaced: true // making our module reusable
})
}
}
})
之后,我们要使用其存储链接 Hello.vue
。我们可能需要州
, getters
,突变
,操作
来自 vuex
。要访问存储空间,我们需要创建 getters
。与突变相同
。
After, we're going to link Hello.vue
with its storage. We may need state
, getters
, mutations
, actions
from vuex
. To access storage we need to create our getters
. Same with mutations
.
Home.vue
Home.vue
<script>
export default {
props: ['id'],
computed: {
count () {
return this.$store.getters[`module${this.id}/count`]
}
},
methods: {
updateCountPlus () {
this.$store.commit(`module${this.id}/updateCountPlus`)
}
}
}
</script>
想象一下,我们有很多 getters
,突变
和操作
。为什么不使用 {mapGetters}
或 {mapMutations}
?当我们有几个模块并且我们知道所需模块的路径时,我们就可以做到。不幸的是,我们无权访问模块名称。
Imagine we have lots of getters
, mutations
and actions
. Why not use {mapGetters}
or {mapMutations}
? When we have several modules and we know the path to module needed, we can do it. Unfortunately, we do not have access to module name.
代码在组件模块执行时运行(当你的app $ b $时b正在启动),而不是在创建组件时。所以这些助手只有在你提前知道模块名称时才能使用
。
The code is run when the component's module is executed (when your app is booting), not when the component is created. So these helpers can only be used if you know the module name ahead of time.
这里几乎没有帮助。我们可以将 getters
和突变
分开,然后将它们作为对象导入并保持清洁。
There is little help here. We can separate our getters
and mutations
and then import them as an object and keep it clean.
<script>
import computed from '../store/moduleGetters'
import methods from '../store/moduleMutations'
export default {
props: ['id'],
computed,
methods
}
</script>
返回 App
组件。我们必须提交我们的变种
,并为 App $ c创建一些
getter
$ C>。为了说明我们如何访问模块中的数据。
Returning to App
component. We have to commit our mutation
and also let's create some getter
for App
. To show how can we access data located into modules.
store.js
store.js
export const store = new Vuex.Store({
state: {
jobs: []
},
getters: {
jobs: state => state.jobs,
sumAll (state, getters) {
let s = 0
for (let i = 1; i <= state.jobs.length; i++) {
s += getters[`module${i}/count`]
}
return s
}
}
...
<$ c $中的完成代码c> App 组件
<script>
import Hello from './components/Hello'
import {mapMutations, mapGetters} from 'vuex'
export default {
components: {
Hello
},
computed: {
...mapGetters([
'jobs',
'sumAll'
])
},
methods: {
...mapMutations([
'addJob'
])
}
}
</script>
这篇关于为动态创建的组件分隔vuex存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!