【问题标题】:VueJS Form does not revert to original after cancel取消后VueJS表单不会恢复到原始状态
【发布时间】:2019-12-24 23:49:28
【问题描述】:

我有一个应用程序,用户可以在其中手动删除帖子中的文本和文件附件。它工作正常,用户可以删除帖子中的文本和附件,但是,问题是当用户选择“取消”按钮时——附件仍然显示已编辑的附件项目。期望的结果是附件恢复到原始列表。

有人对我如何解决这个问题有任何建议吗?

我在这里设置了一个演示:Codesandbox点击 POSTS --> POST ID --> EDIT POST --> 删除附件 --> CANCEL EDIT

我正在使用 props 将数据传递给子组件:

名为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;
      }
    }
  }
};

名为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>&nbsp;
                <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;
      }
    }
  }
};

知道为什么取消按钮不会将附件数组恢复为原始吗?

【问题讨论】:

    标签: javascript vuejs2 vue-cli-3


    【解决方案1】:

    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 是一个道具。你不应该改变一个道具。而是在触发取消事件时在父级中重置您的帖子和attachmentsArray 那里的道具(这将在子组件中自动更新)。

    更新: 在 EditPost 中,当他们删除项目 @click.prevent="$emit('deleteMediaAttachment', attachmentFileName)" 时,您会执行此操作,然后在父项中编辑附件状态。如果您想防止实际删除,一种方法可能是向每个附件对象添加一个“已删除:布尔”字段。然后,在您的编辑方法中,您可以将该字段从 false 切换为 true。在模板中,您将使用 v-if 和 v-for 来有条件地显示基于已删除的附件。如果用户取消,您需要将这些字段切换回 true。

    旁注:在 EditPost 中,您引用了 this.attachmentsBeforeEdit = Object.assign({}, this.attachmentsArray);,但它没有在组件中的任何地方初始化。可能将其作为数据属性包含在内,这样您就不会将其添加到生命周期挂钩中的数据中。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多