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

k10s72fa  于 2022-12-04  发布在  iOS
关注(0)|答案(4)|浏览(143)

问题

我试图在Laravel项目中使用vuejs + axios从我的数据库加载数据。在本地,我可以使用axios发出请求,它返回数据,将其分配给变量,然后将数据输出到DOM。
当我把同样的代码推向生产时,axios请求的执行时间稍长一些,但它似乎足够长,在所有数据返回之前,vuejs就准备好了,当数据试图显示时,给我留下了一个恼人的“未定义属性”错误。有时,在数据加载之前,这个错误会持续20多次刷新。
"我认为问题是什么"
因此,通过阅读,我的猜测是axios没有像它应该做的那样快速地获取数据,因此vuejs已经准备好开始提供数据,但是axios还没有机会收集数据,从而导致undefined error
"我读过的和尝试过的“
我读到过在依赖于数据的对象上使用v-if语句应该可以解决这个问题。但是它没有,如果数据不存在,它会从视图中隐藏对象。例如...
HTML语言

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

Java脚本

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

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

这不起作用,当数据尚未加载时,它不会显示任何内容。

问题

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

更多信息

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

bjp0bcyl

bjp0bcyl1#

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

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

然后 Package 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>
lsmepo6l

lsmepo6l2#

编辑的回答,更好地解释了我的意思。
无论axios获取数据需要1秒还是10秒,您的代码都应该能够正常工作。您不需要检查user.name上的v-if。VueJS具有React性,如果data属性发生变化,它会更新视图。
请参阅此程式码范例。https://codepen.io/bergur/pen/VOXrzR
在这里,我等待10秒钟来填充用户对象
1.{{user.name}}没有显示任何内容,然后Bergur
1.{{ computedName }}显示未定义的Hallgrímsson,因为user.name在10秒内未定义。
1.{{user.address.country}}会掷回错误(无法读取未定义的属性'country'),因为初始数据对象中没有user.address。
因此,一种解决方案是在数据对象中初始定义地址

user: {
  address: {}
}

我的观点是你的初始代码应该工作(当呈现时)。
a)您在您的vue应用程序中使用该名称属性,例如user.name,但没有名称属性。

B)当您呈现第二层属性时,例如user.address.country,因为地址尚未初始定义。

xwmevbvl

xwmevbvl3#

借助lodash的debounce,您可以延迟方法函数或计算属性被调用和执行之间的时间。您还可以区分同一方法创建不同函数的延迟时间,例如,一个函数由安装程序触发,另一个函数由监视程序触发。在我的例子中,在安装程序上调用的函数,需要等待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];
    },
pinkon5k

pinkon5k4#

<div v-if="user">
   <div>
       @{{ user.name }}
   </div>
   <div>
       @{{ user.second_name }}
   </div>
   <div>
       @{{ user.phone }}
   </div>
   <div>
       @{{ user.any }}
   </div>
</div>

相关问题