VueJS 2.x 子组件不会对更改的父属性做出反应

时间:2021-05-31 14:47:34

标签: vue.js vuejs2 vue-component

我遇到了一个问题,即组件无法识别属性的更改。 该组件嵌套了大约 5 层深。故障组件上方的每个组件都会以相同的机制进行更新,并且完美无瑕。 我花了一些时间来解决这个问题,但我找不到。

流程是:

  • 仪表板(更改值并作为道具传递)
  • TicketPreview(使用情况和 传递道具)
  • CommentSection(通过道具)
  • CommentList(错误/道具使用)

到 commentSection 的所有内容都按预期更新,但是 commentList 没有收到更新通知(beforeUpdate 没有被触发)。

由于我测试了很多东西,所以我只会发布commentSection(父)和commenList(子)中的基本代码

<块引用>

免责声明:这是一个没有后端的原型代码,因此典型的 API 请求是通过用户浏览器的 localStorage 解决的。

评论部分

<template>
  <div id="comment-section">
    <p>{{selectedTicket.title}}</p>
    <comment-form :selectedTicket="selectedTicket" />
    <comment-list :selectedTicket="selectedTicket" />
  </div>
</template>

<script>
  import CommentForm from "@/components/comment-section/CommentForm";
  import CommentList from "@/components/comment-section/CommentList";

  export default {
    name: "CommentSection",
    components: {
      CommentForm,
      CommentList,
    },
    props: {
      selectedTicket: Object,
    },
    beforeUpdate() {
      console.log("Comment Section");
      console.log(this.selectedTicket);
    },
    updated() {
      console.log("Comment Section is updated");
    }
  }
</script>

评论列表

<template>
  <div id="comment-list">
    <comment-item
         v-for="comment in comments"
         :key="comment.id"
         :comment="comment"
    />
  </div>
</template>

<script>
  import CommentItem from "@/components/comment-section/CommentItem";

  export default {
    name: "CommentList",
    components: {
      CommentItem,
    },
    data() {
      return {
        comments: Array,
      }
    },
    props: {
      selectedTicket: Object,
    },
    methods: {
      getComments() {
        let comments = JSON.parse(window.localStorage.getItem("comments"));
        let filteredComments = [];
        for(let i = 0; i < comments.length; i++){
          if (comments[i].ticketId === this.selectedTicket.id){
            filteredComments.push(comments[i]);
          }
        }
        this.comments = filteredComments;
      }
    },
    beforeUpdate() {
      console.log("CommentList");
      console.log(this.selectedTicket);
      this.getComments();
    },
    mounted() {
      this.$root.$on("updateComments", () => {
        this.getComments();
      });
      console.log("CL Mounted");
    },
  }
</script>

commentList 组件beforeUpdate()updated() 钩子没有被触发。 我想我可以通过一个传递数据的事件来解决这个问题,但为了便于理解,让我们假设它现在不是一个可行的选择。

2 个答案:

答案 0 :(得分:0)

最好使用观察者,这样会更简单。

您可以使用计算属性而不是通过过滤设置评论的方法,该属性是反应性的,无需监视道具更新。

评论部分

<template>
    <div id="comment-section">
        <p>{{ selectedTicket.title }}</p>
        <comment-form :selectedTicket="selectedTicket" />
        <comment-list :selectedTicket="selectedTicket" />
    </div>
</template>

<script>
import CommentForm from "@/components/comment-section/CommentForm";
import CommentList from "@/components/comment-section/CommentList";

export default {
    name: "CommentSection",
    components: {
        CommentForm,
        CommentList
    },
    props: {
        selectedTicket: Object
    },
    methods: {
        updateTicket() {
            console.log("Comment section is updated");
            console.log(this.selectedTicket);
        }
    },
    watch: {
        selectedTicket: {
            immediate: true,
            handler: "updateTicket"
        }
    }
};
</script>

评论列表

<template>
    <div id="comment-list">
        <comment-item
            v-for="comment in comments"
            :key="comment.id"
            :comment="comment"
        />
    </div>
</template>

<script>
import CommentItem from "@/components/comment-section/CommentItem";

export default {
    name: "CommentList",
    components: {
        CommentItem
    },
    props: {
        selectedTicket: Object
    },
    computed: {
        comments() {
            let comments = JSON.parse(window.localStorage.getItem("comments"));

            let filteredComments = [];
            for (let comment of comments) {
                if (comment.ticketId == this.selectedTicket.id) {
                    filteredComments.push(comment);
                }
            }

            // // using es6 Array.filter()
            // let filteredComments = comments.filter(
            //   (comment) => comment.ticketId == this.selectedTicket.id
            // );
            return filteredComments;
        }
    }
};
</script>

答案 1 :(得分:0)

我发现了问题:由于 commentList 只是一个不使用 prop 中任何值的包装器,因此永远不会触发 beforeUpdate 和 updated 的钩子。 Vue Instance Chart 在这方面具有误导性。该图显示,当数据更改(然后重新渲染,然后更新)时,beforeUpdate 将始终触发,但 beforeUpdate 仅在必须重新渲染组件和父级时触发。 对象按预期更新,只是从未在子组件上触发重新渲染,因为包装器尚未重新渲染。

相关问题