取消后 VueJS 表单不会恢复到原始状态
VueJS Form does not revert to original after cancel
我有一个应用程序,用户可以在其中手动删除 post 中的文本和文件附件。它工作正常,用户可以删除 post 中的文本和附件,但是,问题是当用户选择“取消”按钮时——附件仍然显示已编辑的附件项目。期望的结果是附件恢复到原始列表。
有人对我如何解决这个问题有任何建议吗?
我在这里设置了一个演示:Codesandbox(单击 POSTS --> POST ID --> 编辑 POST - -> 删除附件 --> 取消编辑 )
我正在使用 props 将数据传递给子组件:
Parent component named PostDetail.vue
:
模板:
<section v-if="editPostFormIsVis">
<EditPost
:post="post"
@update="editPostFormIsVis=false"
@cancel="editPostFormIsVis = false"
:attachmentsArray="attachmentsArray"
@deleteMediaAttachment="removeItem"
/>
</section>
脚本:
import attachments from "../../public/attachments.json";
import EditPost from "@/components/EditPost.vue";
export default {
components: {
EditPost
},
data() {
return {
post: {},
editPostFormIsVis: false,
attachmentsArray: attachments
};
},
created() {
this.getPost();
},
methods: {
getPost() {
axios
.get(
"https://jsonplaceholder.typicode.com/posts/" + this.$route.params.id
)
.then(resp => {
this.post = resp.data;
})
.catch(err => {
console.log(err);
});
},
editPost() {
this.editPostFormIsVis = true;
},
removeItem: function(item) {
this.attachmentsArray.attachments.splice(item, 1);
}
},
computed: {
emailAttachmentsFileNames() {
if (this.attachmentsArray.emailAttachments) {
const emailAttachmentsFileNameArray = this.attachmentsArray.emailAttachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return emailAttachmentsFileNameArray;
} else {
return null;
}
},
attachmentsFileNames() {
if (this.attachmentsArray.attachments) {
const attachmentsFileNameArray = this.attachmentsArray.attachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return attachmentsFileNameArray;
} else {
return null;
}
}
}
};
The child component named EditPost.vue
:
模板:
<ul>
<li>Media Attachments
<ul v-if="attachmentsFileNames && attachmentsFileNames.length">
<li v-for="(attachmentFileName, index) in attachmentsFileNames" :key="index">
<a href="
#
">{{ attachmentFileName }}</a>
<button
@click.prevent="$emit('deleteMediaAttachment', attachmentFileName)"
>Delete me!</button>
</li>
</ul>
</li>
</ul>
脚本:
export default {
name: "EditPost",
props: {
post: {
type: Object
},
attachmentsArray: {
type: Object
}
// filenames: {
// type: Array
// }
},
created() {
// clone issue without including observers and reactivity
this.postBeforeEdit = Object.assign({}, this.post);
this.attachmentsArrayBeforeEdit = Object.assign({}, this.attachmentsArray);
//this.attachmentsFileNamesBeforeEdit = Object.assign({}, this.attachmentsFileNames)
},
methods: {
editPost() {
axios
.put("https://jsonplaceholder.typicode.com/posts/" + this.post.id)
.then(response => {
//dosomething
console.log("server response: ", response.status);
})
.then(() => {
this.$emit("update");
})
.catch(err => {
console.log(err);
});
},
cancelEdit() {
// revert UI back to original issue values if user cancels edits
Object.assign(this.post, this.postBeforeEdit);
Object.assign(this.attachmentsArray, this.attachmentsArrayBeforeEdit);
// Object.assign(this.attachmentsFileNames, this.attachmentsFileNamesBeforeEdit);
this.$emit("cancel");
}
},
computed: {
emailAttachmentsFileNames() {
if (this.attachmentsArray.emailAttachments) {
const emailAttachmentsFileNameArray = this.attachmentsArray.emailAttachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return emailAttachmentsFileNameArray;
} else {
return null;
}
},
attachmentsFileNames() {
if (this.attachmentsArray.attachments) {
const attachmentsFileNameArray = this.attachmentsArray.attachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return attachmentsFileNameArray;
} else {
return null;
}
}
}
};
知道为什么取消按钮不会将附件数组恢复为原始数组吗?
在 EditPost.vue
你有
cancelEdit() {
// revert UI back to original issue values if user cancels edits
Object.assign(this.post, this.postBeforeEdit);
Object.assign(this.attachmentsArray, this.attachmentsArrayBeforeEdit);
// Object.assign(this.attachmentsFileNames, this.attachmentsFileNamesBeforeEdit);
this.$emit("cancel");
}
Object.assign(this.post, this.postBeforeEdit);
其中 this.post 是道具。你不应该改变道具。相反,当取消事件被触发时,在父组件中重置你的 post 和 attachmentsArray
道具(这将在子组件中自动更新)。
更新:
在 EditPost 中,当他们删除一个项目 @click.prevent="$emit('deleteMediaAttachment', attachmentFileName)"
时,您会这样做,然后在父级中编辑附件状态。如果您想防止实际删除,一种方法可能是向每个附件对象添加一个 "deleted: boolean" 字段。在您的编辑方法中,您可以将字段从 false 切换为 true。在模板中,您可以将 v-if 与 v-for 结合使用,以有条件地显示基于已删除的附件。如果用户取消,您需要将这些字段切换回 true。
旁注:在 EditPost 中您引用了 this.attachmentsBeforeEdit = Object.assign({}, this.attachmentsArray);
但它没有在组件中的任何地方初始化。可能将其作为数据包含在内属性,因此您不会将其添加到生命周期挂钩中的数据。
我有一个应用程序,用户可以在其中手动删除 post 中的文本和文件附件。它工作正常,用户可以删除 post 中的文本和附件,但是,问题是当用户选择“取消”按钮时——附件仍然显示已编辑的附件项目。期望的结果是附件恢复到原始列表。
有人对我如何解决这个问题有任何建议吗?
我在这里设置了一个演示:Codesandbox(单击 POSTS --> POST ID --> 编辑 POST - -> 删除附件 --> 取消编辑 )
我正在使用 props 将数据传递给子组件:
Parent component named
PostDetail.vue
:
模板:
<section v-if="editPostFormIsVis">
<EditPost
:post="post"
@update="editPostFormIsVis=false"
@cancel="editPostFormIsVis = false"
:attachmentsArray="attachmentsArray"
@deleteMediaAttachment="removeItem"
/>
</section>
脚本:
import attachments from "../../public/attachments.json";
import EditPost from "@/components/EditPost.vue";
export default {
components: {
EditPost
},
data() {
return {
post: {},
editPostFormIsVis: false,
attachmentsArray: attachments
};
},
created() {
this.getPost();
},
methods: {
getPost() {
axios
.get(
"https://jsonplaceholder.typicode.com/posts/" + this.$route.params.id
)
.then(resp => {
this.post = resp.data;
})
.catch(err => {
console.log(err);
});
},
editPost() {
this.editPostFormIsVis = true;
},
removeItem: function(item) {
this.attachmentsArray.attachments.splice(item, 1);
}
},
computed: {
emailAttachmentsFileNames() {
if (this.attachmentsArray.emailAttachments) {
const emailAttachmentsFileNameArray = this.attachmentsArray.emailAttachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return emailAttachmentsFileNameArray;
} else {
return null;
}
},
attachmentsFileNames() {
if (this.attachmentsArray.attachments) {
const attachmentsFileNameArray = this.attachmentsArray.attachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return attachmentsFileNameArray;
} else {
return null;
}
}
}
};
The child component named
EditPost.vue
:
模板:
<ul>
<li>Media Attachments
<ul v-if="attachmentsFileNames && attachmentsFileNames.length">
<li v-for="(attachmentFileName, index) in attachmentsFileNames" :key="index">
<a href="
#
">{{ attachmentFileName }}</a>
<button
@click.prevent="$emit('deleteMediaAttachment', attachmentFileName)"
>Delete me!</button>
</li>
</ul>
</li>
</ul>
脚本:
export default {
name: "EditPost",
props: {
post: {
type: Object
},
attachmentsArray: {
type: Object
}
// filenames: {
// type: Array
// }
},
created() {
// clone issue without including observers and reactivity
this.postBeforeEdit = Object.assign({}, this.post);
this.attachmentsArrayBeforeEdit = Object.assign({}, this.attachmentsArray);
//this.attachmentsFileNamesBeforeEdit = Object.assign({}, this.attachmentsFileNames)
},
methods: {
editPost() {
axios
.put("https://jsonplaceholder.typicode.com/posts/" + this.post.id)
.then(response => {
//dosomething
console.log("server response: ", response.status);
})
.then(() => {
this.$emit("update");
})
.catch(err => {
console.log(err);
});
},
cancelEdit() {
// revert UI back to original issue values if user cancels edits
Object.assign(this.post, this.postBeforeEdit);
Object.assign(this.attachmentsArray, this.attachmentsArrayBeforeEdit);
// Object.assign(this.attachmentsFileNames, this.attachmentsFileNamesBeforeEdit);
this.$emit("cancel");
}
},
computed: {
emailAttachmentsFileNames() {
if (this.attachmentsArray.emailAttachments) {
const emailAttachmentsFileNameArray = this.attachmentsArray.emailAttachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return emailAttachmentsFileNameArray;
} else {
return null;
}
},
attachmentsFileNames() {
if (this.attachmentsArray.attachments) {
const attachmentsFileNameArray = this.attachmentsArray.attachments.map(
item => {
const tokens = item.split("/");
return tokens[tokens.length - 1];
}
);
return attachmentsFileNameArray;
} else {
return null;
}
}
}
};
知道为什么取消按钮不会将附件数组恢复为原始数组吗?
在 EditPost.vue
你有
cancelEdit() {
// revert UI back to original issue values if user cancels edits
Object.assign(this.post, this.postBeforeEdit);
Object.assign(this.attachmentsArray, this.attachmentsArrayBeforeEdit);
// Object.assign(this.attachmentsFileNames, this.attachmentsFileNamesBeforeEdit);
this.$emit("cancel");
}
Object.assign(this.post, this.postBeforeEdit);
其中 this.post 是道具。你不应该改变道具。相反,当取消事件被触发时,在父组件中重置你的 post 和 attachmentsArray
道具(这将在子组件中自动更新)。
更新:
在 EditPost 中,当他们删除一个项目 @click.prevent="$emit('deleteMediaAttachment', attachmentFileName)"
时,您会这样做,然后在父级中编辑附件状态。如果您想防止实际删除,一种方法可能是向每个附件对象添加一个 "deleted: boolean" 字段。在您的编辑方法中,您可以将字段从 false 切换为 true。在模板中,您可以将 v-if 与 v-for 结合使用,以有条件地显示基于已删除的附件。如果用户取消,您需要将这些字段切换回 true。
旁注:在 EditPost 中您引用了 this.attachmentsBeforeEdit = Object.assign({}, this.attachmentsArray);
但它没有在组件中的任何地方初始化。可能将其作为数据包含在内属性,因此您不会将其添加到生命周期挂钩中的数据。