Vuex Action 提交突变
我有一个 vue 应用程序,用户可以在其中随机化标题和副标题或使用自定义输入组件编辑字段。
当用户选择编辑时,我想将更新的标题和副标题从输入组件发送到商店,以便在填写输入组件中所需的值后单击“保存”按钮时改变标题和副标题状态。
目前能够将值从父级传递给子级,并且有一个发射供父级收听,但是,我不确定如何将原始值更新为自定义值并由于 $emit 的结果而获得“未定义” 。
我似乎找不到这个问题的解决方案,我去过的所有论坛都没有帮助,所以我真的希望这里有人可以帮助我解决我的问题;真的很感激。
Parent.vue
<template>
<main class="home-page page">
<div v-if="!editMode">
<div>
<span>Title: </span>{{title}}
</div>
<div>
<span>Subtitle: </span>{{subtitle}}
</div>
<div>
<button @click="randomizeTitleAndSubtitle">
Randomize
</button>
<button @click="onEdit">Edit</button>
</div>
</div>
<div v-else>
<DoubleInput
:value="{ title, subtitle }"
/>
<div>
<button @click="onCancel">Cancel</button>
<button @click="onSave">Save</button>
</div>
</div>
</main>
</template>
<script>
// @ is an alias to /src
import DoubleInput from '@/components/DoubleInput.vue';
import { mapState, mapActions } from 'vuex';
export default {
name: 'Parent',
components: {
DoubleInput,
},
data() {
return {
editMode: false,
};
},
computed: {
...mapState(['title', 'subtitle']),
},
methods: {
...mapActions(['randomizeTitleAndSubtitle', 'updateTitleAndSubtitle']),
onEdit() {
this.editMode = true;
},
onCancel() {
this.editMode = false;
},
onSave() {
this.editMode = false;
const newTitle = this.title;
const newSubtitle = this.subtitle;
this.updateTitleAndSubtitle({ newTitle, newSubtitle });
},
},
mounted() {
this.randomizeTitleAndSubtitle();
},
};
</script>
Child.vue
<template>
<div>
<label>Edit Title: </label>
<input type="text" ref="title" :value="value.title" @input="updateValue()" />
<label>Edit Subtitle: </label>
<input type="text" ref="subtitle" :value="value.subtitle" @input="updateValue()" />
</div>
</template>
<script>
export default {
name: 'Child',
props: ['value'],
methods: {
updateValue() {
this.$emit('input', {
title: this.$refs.title.value,
subtitle: this.$refs.subtitle.value,
});
},
},
};
</script>
商店
import Vue from 'vue';
import Vuex from 'vuex';
import randomWords from 'random-words';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
title: '',
subtitle: '',
},
mutations: {
UPDATE_TITLE(state, value) {
state.title = value;
},
UPDATE_SUBTITLE(state, value) {
state.subtitle = value;
},
},
actions: {
randomizeTitle({ commit }) {
const newTitle = randomWords();
commit('UPDATE_TITLE', newTitle);
},
randomizeSubtitle({ commit }) {
const newSubtitle = randomWords();
commit('UPDATE_SUBTITLE', newSubtitle);
},
randomizeTitleAndSubtitle({ dispatch }) {
dispatch('randomizeTitle');
dispatch('randomizeSubtitle');
},
updateTitleAndSubtitle({ commit }, value) {
const payload = {
title: value.title || null,
subtitle: value.subtitle || null,
};
commit('UPDATE_TITLE', payload);
commit('UPDATE_SUBTITLE', payload]);
},
},
modules: {
},
});
I have a vue app where a user can randomize a title and subtitle OR edit the fields using a custom input component.
When a user chooses to edit, I'd like to send the updated title and subtitle from the input component to the store to mutate the title and subtitle state when clicking the save button after filling out the values desired in the input component.
Currently able to pass values from parent to child and had an emit present for the parent to listen to, however, I'm not sure how to update the original values to the custom ones and get "undefined" as a result from the $emit.
I can't seem to find a solution to this problem, all the forums I have been on haven't helped so I really hope someone on here can help me with my problem; would really appreciate it.
Parent.vue
<template>
<main class="home-page page">
<div v-if="!editMode">
<div>
<span>Title: </span>{{title}}
</div>
<div>
<span>Subtitle: </span>{{subtitle}}
</div>
<div>
<button @click="randomizeTitleAndSubtitle">
Randomize
</button>
<button @click="onEdit">Edit</button>
</div>
</div>
<div v-else>
<DoubleInput
:value="{ title, subtitle }"
/>
<div>
<button @click="onCancel">Cancel</button>
<button @click="onSave">Save</button>
</div>
</div>
</main>
</template>
<script>
// @ is an alias to /src
import DoubleInput from '@/components/DoubleInput.vue';
import { mapState, mapActions } from 'vuex';
export default {
name: 'Parent',
components: {
DoubleInput,
},
data() {
return {
editMode: false,
};
},
computed: {
...mapState(['title', 'subtitle']),
},
methods: {
...mapActions(['randomizeTitleAndSubtitle', 'updateTitleAndSubtitle']),
onEdit() {
this.editMode = true;
},
onCancel() {
this.editMode = false;
},
onSave() {
this.editMode = false;
const newTitle = this.title;
const newSubtitle = this.subtitle;
this.updateTitleAndSubtitle({ newTitle, newSubtitle });
},
},
mounted() {
this.randomizeTitleAndSubtitle();
},
};
</script>
Child.vue
<template>
<div>
<label>Edit Title: </label>
<input type="text" ref="title" :value="value.title" @input="updateValue()" />
<label>Edit Subtitle: </label>
<input type="text" ref="subtitle" :value="value.subtitle" @input="updateValue()" />
</div>
</template>
<script>
export default {
name: 'Child',
props: ['value'],
methods: {
updateValue() {
this.$emit('input', {
title: this.$refs.title.value,
subtitle: this.$refs.subtitle.value,
});
},
},
};
</script>
Store
import Vue from 'vue';
import Vuex from 'vuex';
import randomWords from 'random-words';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
title: '',
subtitle: '',
},
mutations: {
UPDATE_TITLE(state, value) {
state.title = value;
},
UPDATE_SUBTITLE(state, value) {
state.subtitle = value;
},
},
actions: {
randomizeTitle({ commit }) {
const newTitle = randomWords();
commit('UPDATE_TITLE', newTitle);
},
randomizeSubtitle({ commit }) {
const newSubtitle = randomWords();
commit('UPDATE_SUBTITLE', newSubtitle);
},
randomizeTitleAndSubtitle({ dispatch }) {
dispatch('randomizeTitle');
dispatch('randomizeSubtitle');
},
updateTitleAndSubtitle({ commit }, value) {
const payload = {
title: value.title || null,
subtitle: value.subtitle || null,
};
commit('UPDATE_TITLE', payload);
commit('UPDATE_SUBTITLE', payload]);
},
},
modules: {
},
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我遇到的最大问题是 Vuex 商店,而不是我想象的父子生命周期。发出工作得很好,需要向自定义输入组件添加一些计算属性。我接近商店的方式完全倒退,并将 updateTitleAndSubtitle() 操作分解为如下所示。最后,添加了一个 @input,它将更新的值对象发送到 onEdit() 以将值设置为数据中的空对象。然后,使用该对象和新值来分派/提交到商店! Vualá ~ 期望的行为,没有错误,最终花了一些时间弄清楚了。
我缺少的是将新发出的数据对象传递给存储操作,然后改变状态。此代码挑战背后的整个概念是从存储中获取数据,通过组件修改数据,将修改后的数据发送回存储,然后更改状态。对此有点过分,但这是我在工作中解决现有应用程序中更大问题所需的实践和概念。
这是代码细分!
自定义输入:
父项:
商店:
Where I was having the biggest issue was most in the Vuex store, not the parent to child lifecycle like I thought. The emit was working just fine and needed to add in some computed properties to the custom input component. How I was approaching the store was completely backwards and gutted the updateTitleAndSubtitle() action to what's shown below. And lastly, added an @input that would send the updated object of values to onEdit() to set the values to an empty object in the data. Then, use that object with the new values to dispatch/commit to the store! Vualá ~ the desired behavior, no errors, and ended up figuring it out with some time.
What I was missing was passing the new emitted data object to a store action to then mutate the state. The whole concept behind this code challenge was to take in data from the store, modify it through a component, send back the modified data to the store to then change the state. A bit overkill for this, BUT it's the practice and concept I needed to approach a much larger problem in an existing application at work.
Here's the code breakdown!
Custom Input:
Parent:
Store:
您在
onSave()
方法中调用updateTitleAndSubtitle
不会将新标题和副标题传递给操作。另外,我会犹豫是否使用
state.title
和state.subtitle
作为编辑模式变量,因为按照惯例,您应该只通过突变来更改这些值。相反,将本地 var 作为 prop 传递给您的子组件,并使用它调用方法。鉴于您的评论,更能理解为什么代码不必要地复杂。只要您的
@input
处理程序不尝试写回状态变量,就可以将状态变量作为 props 传递。你不需要本地变量。试试这个:与
Your call to
updateTitleAndSubtitle
in theonSave()
method isn't passing the new title and subtitle to the action.Also, I would hesitate using
state.title
andstate.subtitle
as your edit mode vars as conventionally you should only change those values via mutations. Instead, pass a local var as the prop to your child component and call the method using it instead.Given your comments it makes more sense why the code is unnecessarily complex. It's perfectly fine to pass your state vars as props as long as your
@input
handler doesn't try to write back to it. You don't need the local var. Try this:with