这个问题让我陷入了一点困境。不幸的是,我在这里找不到答案(要求也没有帮助)。所以经过一些研究并在这里和那里询问后,似乎我得到了这个问题的解决方案。
如果您有一个问题,您已经知道答案,而且您 我想在公开场合记录这些知识,以便其他人 (包括你自己)可以在以后找到它。
当然,我的答案可能不是理想的答案,而且我知道不是,这是我发帖的关键点 - 改进它。
注意,我没有在示例中使用操作。这个想法是一样的。
让我们从陈述问题开始:
想象一下,我们App.vue
动态生成名为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
export const store = new Vuex.Store({
state: {
jobs: []
}
})
我们正在使用v-for
指令通过迭代数组jobs
来生成组件。到目前为止,我们的store
仅包含state
个空数组。
按钮New
应该做两件事:
1)创建新组件Hello
,换句话说,将元素添加到jobs
(让它成为数字),这些元素将被指定为{{1}和key
的{{1}},并以id
的形式传递给本地组件。
2)生成本地商店 - 模块 - 保持任何数据作用于新创建的组件。
<hello>
props
简单组件 - 使用添加1的按钮输入。
答案 0 :(得分:20)
对于NEW
按钮 - 生成组件的第一次操作,我们将mutation
添加到store.js
mutations: {
addJob (state) {
state.jobs.push(state.jobs.length + 1)
...
}
其次,创建本地模块。在这里,我们将使用reusableModule
生成模块的多个实例。该模块我们保存在单独的文件中以方便。另外,注意使用函数来声明模块状态。
const state = () => {
return {
count: 0
}
}
const getters = {
count: (state) => state.count
}
const mutations = {
updateCountPlus (state) {
state.count++
}
}
export default {
state,
getters,
mutations
}
要使用reusableModule
我们导入它并应用动态模块注册。
<强> 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
与其存储空间相关联。我们可能需要state
中的getters
,mutations
,actions
,vuex
。要访问存储空间,我们需要创建getters
。与mutations
相同。
<强> 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
,mutations
和actions
。为什么不使用{mapGetters}
或{mapMutations}
?当我们有几个模块并且我们知道所需模块的路径时,我们就可以做到。不幸的是,我们无法访问模块名称。
代码在执行组件模块时运行(当您的应用程序运行时) 正在启动),而不是在创建组件时。所以这些助手可以 只有在提前知道模块名称时才能使用。
这里几乎没有帮助。我们可以将getters
和mutations
分开,然后将它们作为对象导入并保持清洁。
<script>
import computed from '../store/moduleGetters'
import methods from '../store/moduleMutations'
export default {
props: ['id'],
computed,
methods
}
</script>
返回App
组件。我们必须提交mutation
,并为getter
创建一些App
。为了说明我们如何访问位于模块中的数据。
<强> 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
}
}
...
完成App
组件
<script>
import Hello from './components/Hello'
import {mapMutations, mapGetters} from 'vuex'
export default {
components: {
Hello
},
computed: {
...mapGetters([
'jobs',
'sumAll'
])
},
methods: {
...mapMutations([
'addJob'
])
}
}
</script>
答案 1 :(得分:1)
您好,感谢您发布问题和解决方案。
几天前,我开始学习Vuex,遇到了类似的问题。我已经检查了您的解决方案,并提出了我的方法,该方法不需要注册新模块。我发现这太过分了,说实话,我不明白您为什么这么做。我总是有可能误解了这个问题。
为了清晰和演示起见,我创建了带有一些差异的标记副本。
我有:
JobList.vue(负责包装作业列表项)
<template>
<div>
<job v-for="(job, index) in jobs" :data="job" :key="job.id"></job>
<h3>Create New Job</h3>
<form @submit.prevent="addJob">
<input type="text" v-model="newJobName" required>
<button type="submit">Add Job</button>
</form>
</div>
</template>
<script>
import store from '../store/index'
import job from './job';
export default {
components: { job },
data() {
return {
newJobName: ''
};
},
computed: {
jobs() {
return store.state.jobs.jobs;
}
},
methods: {
addJob() {
store.dispatch('newJob', this.newJobName);
}
}
}
</script>
工作
<template>
<div>
<h5>Id: {{ data.id }}</h5>
<h4>{{ data.name }}</h4>
<p>{{ data.active}}</p>
<button type="button" @click="toggleJobState">Toggle</button>
<hr>
</div>
</template>
<script>
import store from '../store/index'
export default {
props: ['data'],
methods: {
toggleJobState() {
store.dispatch('toggleJobState', this.data.id);
}
}
}
</script>
最后是jobs.js Vuex模块文件:
export default {
state: {
jobs: [
{
id: 1,
name: 'light',
active: false
},
{
id: 2,
name: 'medium',
active: false
},
{
id: 3,
name: 'heavy',
active: false
}
]
},
actions: { //methods
newJob(context, jobName) {
context.state.jobs.push({
id: context.getters.newJobId,
name: jobName,
active: false
});
},
toggleJobState(context, id) {
context.state.jobs.forEach((job) => {
if(job.id === id) { job.active = !job.active; }
})
}
},
getters: { //computed properties
newJobId(state) { return state.jobs.length + 1; }
}
}
可以在商店中添加新作业,并且正如“活动”属性所建议的那样,您可以控制每个单独的作业,而无需新的自定义vuex模块。