【问题标题】:How to force rerender of one Vue component from another如何强制从另一个 Vue 组件重新渲染一个 Vue 组件
【发布时间】:2019-07-03 11:40:08
【问题描述】:

我有一个购物篮,当我从一个应用程序中选择“添加到购物篮”时,我希望购物篮能够实时重新加载。添加到购物篮时,我将此项目发布到 api。篮子从这个 api 中提取并呈现篮子组件中的数据。

我正在使用 EventBus 来告诉购物篮组件已添加了一个新项目,但是在我的 $on 函数中,$forceUpdate() 或发出另一个提取请求都不会使用新项目重新呈现组件。

这是在我的项目组件中:

methods: {
submit(e){
  e.preventDefault()
  let data = this.createBasketObject(this.experience)
  fetch('http://localhost:3000/api/basket', {
    method: 'POST',
    body: JSON.stringify(data),
    headers: { 'Content-Type': 'application/json'}
  })
  .then( eventBus.$emit('basket-updated', true))
}

这是在我的购物篮组件中:

<template lang="html">
  <div class="">
    <h3>Basket</h3>
    <basket-item
      v-for="item in items"
      :key="item._id"
      :item="item"
    />
    <p>Total: £{{ total}}</p>
  </div>

<script>
import BasketItem from './BasketItem.vue';
import { eventBus } from '../main.js';

export default {
  name: 'basket',
  data(){
    return {
      items: [],
      total: 0
    }
  },
  components: {
    'basket-item': BasketItem
  },
  mounted(){
    fetch('http://localhost:3000/api/basket')
    .then(res => res.json())
    .then(data => this.items = data)
    .then(items => this.calcTotal(items))

    eventBus.$on('basket-updated', (data) => {
      if(data){
        this.$forceUpdate()
      }
    })
  }

我实际上是在尝试像在 React 中一样执行 setState,但在我刷新页面之前,购物篮不会更新。

有没有我可以在 Vue 中做到这一点而不使用套接字之类的东西?

谢谢

【问题讨论】:

    标签: javascript vuejs2 vue-component


    【解决方案1】:

    我认为您需要在添加新商品时重新加载购物篮商品,如果您需要“与服务器往返(将新商品发送到服务器,一些计算,返回到前端并更新购物车)” . 所以:将篮子加载放在一个单独的方法中,从挂载中调用它,然后在篮子更新事件中再次调用它: 这是最短的答案:

    LoadBasket() {
     fetch('http://localhost:3000/api/basket')
        .then(res => res.json())
        .then(data => this.items = data)
        .then(items => this.calcTotal(items));
    }
    
    mounted(){
      //The first time:
      this.LoadBasket();
    
      eventBus.$on('basket-updated', (data) => {
          if(data){
             //on basket updated
              this.LoadBasket();
          }
        });
    }
    

    请记住,Data 是一个“反应性”属性:如果它发生变化,那么表示也将被更新(如果需要,tnx 到 VueJS 中使用的虚拟 dom):不需要调用“刷新 UI”方法.

    顺便说一句,如果您只需要将刚刚创建的项目添加到 Items 列表中,您只需将其推送到数组中:

    this.Items.push(newItem);
    

    PS:我建议您查看 Vuex (https://vuex.vuejs.org/guide/state.html) 来管理您的应用程序的状态:它稍微复杂一些,但可以更好地设计您的应用程序。

    【讨论】:

    • 谢谢。我尝试过类似 loadbasket 功能的东西,但它在加载页面时没有反应。我一次只添加一个项目,因此传递该项目并将其推送到项目数据中是可行的。
    猜你喜欢
    • 2017-05-08
    • 2018-08-20
    • 2020-12-04
    • 2019-04-19
    • 2017-11-09
    • 2019-03-20
    • 2021-02-14
    • 2021-08-17
    • 2020-08-09
    相关资源
    最近更新 更多