【问题标题】:How can I rerender parent component if child component changes如果子组件发生更改,如何重新渲染父组件
【发布时间】:2020-01-20 13:46:09
【问题描述】:

我正在开发一个书籍跟踪器应用程序,它可以跟踪您已阅读或将要阅读的书籍。我在服务器端使用 Vue.js 和 Express.js。共有三个列表(类别)。我正在尝试应用按钮更改书籍类别的功能(即从“当前阅读”到“已完成”)。有用。但我必须重新加载整个页面才能看到结果。 所以我有一个组件“我的书”,其中包括组件“书单”,我将“listType”作为道具传递并呈现所有三个列表。在“书单”组件中,我有 v-for 渲染所有书籍并使用“书”组件和书对象作为道具。 'book' 组件有用于更改类别的按钮。因此,当我按下其中一个按钮时,我可以在服务器端更改 listType 并更新数据库条目,甚至重新渲染“书”组件,但是如果不刷新整个列表,我就无法达到我的书从一个列表移动到另一个列表的地步页。

//mybooks 组件

<template> 
   <BookList listType="current" />
   <BookList listType="wantToRead" />
   <BookList listType="finished" />
</template>

//书单组件

<template> 
    <div v-for="bookElement in bookList" :key="bookElement.id">
      <Book :book="bookElement" />
    </div>
</template>

<script> 
export default {
  data() {
    return {
      bookList: []
    };
  },
  components: {
    Book
  },
  props: ["listType"],
  watch: {
    "$route.query.searchDB": {
      //once a query string search value changes, get list of books from server
      immediate: true,
      async handler(value) {
        const list = (await BooksService.index(value)).data;

        //filter books by categories
        this.bookList = list.filter(element => {
          return element.listType === this.listType;
        });
      }
    }
  }
</script>

// 图书组件

//template to render author, title etc
//and button for example
<button @click="changeTo('current', book.id)">Change to current</button>

<script>
import BooksService from "@/services/BooksService";
export default {
  data() {
    return {
      isCurrent: false,
      isLater: false,
      isFinished: false
    };
  },
  props: ["book"],
  mounted() {
    if (this.book.listType === "current") {
      this.isCurrent = true;
    } else if (this.book.listType === "finished") {
      this.isFinished = true;
    } else this.isLater = true;
  },
  methods: {

    async changeTo(list) {
      this.book.listType = list;

      try {
        await BooksService.put(this.book);
      } catch (err) {
        this.error = err;
      }      
    }
  }
};
</script>

【问题讨论】:

  • 通常,如果您希望子组件的逻辑影响父组件,那么您需要将该逻辑上移到父组件。然后,您可以作为道具或emit 传递对它的引用。否则,即使孩子的状态发生变化,您的父组件也不会受到其孩子正在做什么的影响。

标签: javascript vue.js


【解决方案1】:

您在正确的轨道上,但您不了解 Vue 希望处理数据的方式。

你做对了

你的父组件 booklist 通过 prop v-bind :book 将数据传递给子组件 Book

现在需要做什么

Book 发生变化时,它需要执行诸如$emit('bookChanged', book) 之类的发射事件,以便任何父组件都知道其子组件中发生了某些事情并需要做出反应。所以在我的例子中你的代码看起来像

<Book :book="bookElement" @bookChanged="RefreshMe_Method"  />

此时 RefreshMe_Method 可以做几件事之一,这个简单的方法是简单地更新传递给 Prop :book 的数据,或者另一个更强力的选项是调用 this.$forceUpdate(); 但我确信只是更新数据会自动刷新你想要的数据。

如何处理数据

  1. 家长将数据传递给孩子(想想第一天的学校午餐)。
  2. Child 显示数据、改变数据(本地副本而不是 Prop)或执行一些特殊操作。 (扔掉蔬菜)
  3. 孩子为此感到非常自豪,它想让每个人都知道所以它@98​​7654329@ 改变了。
  4. 所有父母都看到了这一点,并且可以从这一点开始做他们想做的事。 (将孩子接地并仅包装 Brocolli)

【讨论】:

  • 感谢您的回答。但它不起作用。我在 Book 组件和 BookList 组件中执行 $emit 捕获它并使用方法,但是 this.$forceUpdate() 不会改变任何东西。然后我尝试对 BookList 和 MyBooks 组件($emit 并捕获它)做同样的事情并在那里尝试 forceUpdate,但效果不佳......
  • @NikitaSkopin 您是否正在分配数据以更新孩子的道具? forceUpdate 只会刷新渲染,如果数据相同则不会有变化。
  • 是的,我在使用 forceUpdate 之前做过,但是做错了。所以最终我解决了我的问题。谢谢!
  • @NikitaSkopin 如果此答案帮助您解决了问题,请将其标记为已回答。祝你编码好运!
猜你喜欢
  • 2022-08-10
  • 1970-01-01
  • 2020-02-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多