简体   繁体   English

如何强制将一个Vue组件从另一个组件重新渲染

[英]How to force rerender of one Vue component from another

I have a shopping basket where when I select 'add to basket' from one app I want the basket to live reload. 我有一个购物篮,当我从一个应用程序中选择“添加到购物篮”时,我希望该购物篮重新加载。 When adding to the basket i'm posting this item to an api. 当添加到购物篮时,我将此商品发布到api。 The basket fetch's from this api and renders the data in the basket component. 从此api获取购物篮,并将数据呈现在购物篮组件中。

I'm using an EventBus to tell the basket component that a new item has been added however within my $on function neither $forceUpdate() or making another fetch request re renders the component with the new item. 我正在使用EventBus告诉购物篮组件已添加了新项目,但是在$on函数中,无论是$forceUpdate()还是发出另一个提取请求都不会用新项目重新渲染组件。

This is in my item component: 这是在我的项目组件中:

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))
}

and this is in my basket component: 这是在我的购物篮组件中:

<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()
      }
    })
  }

I'm essentially trying to do a setState like in React but the basket doesn't update until I refresh the page. 我本质上是想像在React中那样做一个setState,但是直到刷新页面后篮子才会更新。

Is there anyway I can do this in Vue without using something like sockets? 无论如何,我可以在Vue中执行此操作而无需使用套接字?

Thanks 谢谢

I think that you need to RELOAD the basket items on new item added, IF you need the 'roundtrip with the server (send the new item to the server, some calcs, back to front-end with the cart updated)'. 我认为您需要在添加的新项目上重新加载购物篮项目,如果您需要“与服务器往返(将新项目发送到服务器,进行一些计算,并在更新购物车后返回前端)”。 So: put in a separate method the basket load, call it from the mounted and again on the basket-updated event: This is the shortest answer: 因此:将篮筐负载放入一个单独的方法,从已安装的篮筐负载中调用它,然后在篮筐更新事件中再次调用它:这是最短的答案:

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();
      }
    });
}

Remember that the Data is a 'reactive' property: if it change then also the presentation will be updated (if needed, tnx to the virtual dom used in VueJS): there is no need to call a 'refresh UI' method. 请记住,数据是一个“反应性”属性:如果更改了该属性,还将更新演示文稿(如果需要,将tnx转换为VueJS中使用的虚拟dom):无需调用“刷新UI”方法。

By the way, if you need only to add the just created item to the Items list you need only to push it into the array: 顺便说一句,如果只需要将刚创建的项目添加到“项目”列表中,则只需将其推入数组即可:

this.Items.push(newItem);

PS: I recommend you to take a look on Vuex ( https://vuex.vuejs.org/guide/state.html ) for the state management of your application: it's little bit more complex but permit a better design of your application. PS:我建议您使用Vuex( https://vuex.vuejs.org/guide/state.html )进行应用程序的状态管理:这有点复杂,但可以更好地设计应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM