Get component to wait for asynchronous data before rendering

时光总嘲笑我的痴心妄想 提交于 2020-01-23 03:05:20

问题


I am calling an endpoint to bring back an object, which does fetch the data, however not fast enough for the component to grab the data and render. Instead, the component renders with blank values where there should be data.

If I break point the code on creation, then continue maybe a second later, the text correctly renders.

How do I implement it to not render until the data is back?

My API call:

checkScenarioType: function () {
    this.$http.get('ScenariosVue/GetScenarioTypeFromParticipant/' + this.ParticipantId).then(response => {
        // get body data
        this.ScenarioType = response.body.value;
        if (this.ScenarioType.timeConstraint) {
            store.commit('switchConstraint');
        }
    }, response => {
        // error callback
    });
}

The component having the issues:

var questionArea = Vue.component('questionarea', {
    props: ["scenariotype"],
    data: function () {
        return ({
            position: "",
            vehicleType: ""
        });
    },
    methods: {
        transformValuesForDisplay: function () {
            switch (this.scenariotype.perspective) {
                case 1: {
                    this.position = "Driver";
                    this.vehicleType = "Autonomous";
                    break;
                }
                case 2: {
                    this.position = "Passenger";
                    this.vehicleType = "Manually Driven";
                    break;
                }
                case 3: {
                    this.position = "Driver";
                    this.vehicleType = "Manually Driven";
                    break;
                }
            }
        }
    },
    beforeMount() {
        this.transformValuesForDisplay();
    },
    template: 
    `<h1>You are the {{ this.position }}! What should the {{ this.vehicleType }} car do?</h1>`
});

回答1:


In cases like there's asynchronous loading of data, we typically use a simple v-if to hide the element until the data is present.

The template would be like:

<h1 v-if="position">You are the {{ position }}! What should the {{ vehicleType }} car do?</h1>

Notice the use of this in the template is unnecessary.

Also, in your case, instead of the beforeMount() hook, you would add a (deep/immediate) watch to the prop, to pick up changes when it is loaded externally:

  watch: {
    scenariotype: {
      handler: function(newValue) {
            this.transformValuesForDisplay();
      },
      deep: true,
      immediate: true
    }
  },

Full demo below.

Vue.component('questionarea', {
  props: ["scenariotype"],
  data: function () {
    return ({
      position: "",
      vehicleType: ""
    });
  },
  methods: {
    transformValuesForDisplay: function () {
      switch (this.scenariotype.perspective) {
        case 1: {
          this.position = "Driver";
          this.vehicleType = "Autonomous";
          break;
        }
        case 2: {
          this.position = "Passenger";
          this.vehicleType = "Manually Driven";
          break;
        }
        case 3: {
          this.position = "Driver";
          this.vehicleType = "Manually Driven";
          break;
        }
      }
    }
  },
  watch: {
  	scenariotype: {
      handler: function(newValue) {
    		this.transformValuesForDisplay();
      },
      deep: true,
      immediate: true
    }
  },
  template: 
  `<h1 v-if="position">You are the {{ position }}! What should the {{ vehicleType }} car do?</h1>`
});

new Vue({
  el: '#app',
  data: {
  	ScenarioType: {perspective: null}
  },
  methods: {
    checkScenarioType: function () {
      this.$http.get('https://reqres.in/api/users/2').then(response => {
        // get body data
        this.ScenarioType.perspective = response.body.data.id; // for testing purposes only
      }, response => {
        // error callback
      });
    }
  },
  mounted: function() {
    this.checkScenarioType();
  }
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-resource"></script>

<div id="app">
  <p>Notice while it is null, the h1 is hidden: {{ ScenarioType }}</p>
  <br>
  <questionarea :scenariotype="ScenarioType"></questionarea>
</div>


来源:https://stackoverflow.com/questions/49477230/get-component-to-wait-for-asynchronous-data-before-rendering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!