在axios请求返回数据之前加载Vuejs页面

时间:2019-05-24 10:35:21

标签: javascript laravel vue.js axios

问题

我正在尝试使用Laravel项目中的vuejs + axios从数据库中加载数据。在本地,我可以使用axios发出请求,它会返回数据,将其分配给变量,然后将数据输出到DOM。

当我将相同的代码推送到生产环境时,axios请求需要花费更长的时间来执行,但似乎已经足够长,以至于vuejs在返回所有数据之前就已经准备好了,这给我带来了一个烦人的“未定义属性”错误尝试显示数据。有时,在加载数据之前,此错误会持续刷新20多次。

我认为问题所在

因此,我从阅读中得出的猜测是axios不能像应有的那样快地获取数据,因此vuejs可以开始提供数据了,但是axios还没有机会收集数据,导致{ {1}}

我已阅读并尝试过的内容

我已阅读到在依赖于数据的对象上使用undefined error语句应该可以解决此问题。但事实并非如此,如果没有数据,它所做的一切都会将对象隐藏在视图之外。例如...

HTML

v-if

JAVASCRIPT

<!-- If user.name exists, display user.name -->
<div v-if="user.name">
    @{{ user.name }}
</div>

这不起作用,当尚未加载数据时,它什么也不显示。

问题

如何确保显示加载的数据并且不返回未定义的错误?我能想到的唯一方法是允许用户在失败的尝试中“单击以检索数据”。

其他信息

我不使用vue模板,子/父结构或任何vue库。我正在通过CDN导入vue.js,并在页面中的脚本中使用它,如上所示。我不确定是否像这样使用它会引起任何此类限制,我只是在基本的基础上学习了vue.js,这对公司和老板都适用...

3 个答案:

答案 0 :(得分:1)

编辑后的答案,以更好地解释我的意思。

无论axios花费1秒钟还是10秒钟来获取数据,您的代码都应该可以工作。您不必在user.name上使用v-if进行检查。 VueJS具有反应性,如果data属性发生更改,则会更新视图。

请参见此代码示例。 https://codepen.io/bergur/pen/VOXrzR

我在这里等待10秒以填充用户对象

  1. {{user.name}}不显示任何内容,然后显示Bergur
  2. {{计算名称}}显示未定义的Hallgrímsson,因为user.name在10秒钟内未定义。
  3. {{user.address.country}}将引发错误(无法读取未定义的属性“ country”),因为在初始数据对象中user.address不可用。

一种解决方案是首先在数据对象中定义地址

user: {
  address: {}
}

我的意思是,您的初始代码应该可以工作(渲染时)。未定义的错误会在以下情况出现

a)您正在vue应用中使用该name属性,例如,在没有name属性时使用user.name。

b)渲染第二级属性时,例如user.address.country,因为最初并未定义地址。

答案 1 :(得分:0)

您可以添加“已加载”布尔属性来解决此问题。例如:

<script>
    new Vue({
        el: '#container',
        data: {
            isLoaded: false,
            user: {}
        },
        mounted() {
            this.getUserData();
        },
        methods: {
            getUserData(){
                axios.post('/user/get').then((response) => {

                    this.isLoaded = true;

                    // Check the response was a success
                    if(response.data.status === 'success')
                    {
                        this.user = response.data.user;
                    }
                });
            },
        }
    })
</script>

然后包装您的html以检查数据是否已加载:

<div v-if="isLoaded">
   <!-- If user.name exists, display user.name -->
   <div v-if="user.name">
       @{{ user.name }}
   </div>
</div>

然后您还可以显示一个加载程序:

<div v-if="isLoaded">
   <!-- If user.name exists, display user.name -->
   <div v-if="user.name">
       @{{ user.name }}
   </div>
</div>

<div v-else>
    Loading...
</div>

答案 2 :(得分:0)

借助lodash的反跳功能,您可以延迟调用和执行方法函数或计算属性之间的时间。 同样,您可以区分创建不同功能的相同方法的延迟时间。一个由骑乘触发,另一个由观察者触发。以我为例,该函数在挂载时需要等待,直到axios调用返回响应并设置store.state.TableDataInit为止。在观察者的情况下,由于已经设置了store.state变量,因此它可以立即运行,无需再等待axios响应。例如:

created: function() {
    this.setInitRange = _.debounce(this.setRange, 600);
    this.setInitBoundaries = _.debounce(this.setBoundaries, 600);
    this.setWatchRange = this.setRange;
    this.setWatchBoundaries = this.setBoundaries;
},
mounted() {    
    this.setInitRange(this.selected);
    this.setInitBoundaries();
},

watch: {
    selected() {      
      store.commit("storedMetric", this.selected);
      this.setWatchRange(this.selected); 
      this.setWatchBoundaries();
    }    
},
methods: {
    setRange(value) {
      var metric = value;
      var dataArray = store.state.TableDataInit; 
      const maxMetric = dataArray.reduce(function(prev, current) {
        return _.get(prev, metric) > _.get(current, metric) ? prev : current;
      })[metric];
      const minMetric = dataArray.reduce(function(prev, current) {
        return _.get(prev, metric) < _.get(current, metric) ? prev : current;
      })[metric];
      this.range = [minMetric, maxMetric];
      store.commit("storedOutBoundRange", this.range);
   },
   setBoundaries() {
      this.min = store.state.OutBoundRange[0];
      this.max = store.state.OutBoundRange[1];
    },