javascript Vue JS 在渲染前等待数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/54024406/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:21:09  来源:igfitidea点击:

Vue JS waiting for data before rendering

javascriptvue.jsvuejs2async-await

提问by Pablo Araya

I'm stuck since a few weeks in a problem with rendering data with VueJS.

几周以来,我一直在使用 VueJS 渲染数据的问题中陷入困境。

What I'm doing is making some axios calls (one inside another). My problem is that the data is rendered before the calls has completed, so the view is not showing anything.

我正在做的是进行一些 axios 调用(一个在另一个内部)。我的问题是数据在调用完成之前呈现,因此视图没有显示任何内容。

I saw some codes that do some "await" and "Async calls" but nothing seems to solve my problem.

我看到一些代码做了一些“等待”和“异步调用”,但似乎没有解决我的问题。

Also there is something similar here Get component to wait for asynchronous data before renderingBut isn't working either

这里也有类似的东西 Get component to wait asynchronous data before renderingBut is not working or

here is my code:

这是我的代码:

<template>
 <div class="m-portlet m-portlet--full-height" m-portlet="true" id="m_portlet_validate_agenda">
...
<div class="m-portlet__body">
    <div class="tab-content">
        <div class="tab-pane active" id="m_widget2_tab1_diagnose">
            <div class="m-widget2">
                <div v-for="diagnose in diagnoses" v-if="diagnoses.length" :class="'m-widget2__item m-widget2__item--' + diagnose.delayColor[0]">
                    <div class="m-widget2__checkbox" >
                        <label class="m-checkbox m-checkbox--solid m-checkbox--single m-checkbox--brand">
                            <span class="m--bg-white" v-html="diagnose.concurrence"></span>
                        </label>
                    </div>
                    <div class="m-widget2__agenda col-2">
                        {{ diagnose.started_at | moment("HH:mm A") }}
                    </div>
                    <div class="m-widget2__desc" v-if="!isFetching">
                        <div>
                            <span class="m-widget2__text">

                            </span><br>
                            <span class="m-widget2__user-name">
                                <a href="#" class="m-widget2__link m-link">
                                Paciente: 
                                {{ diagnose.details[0].name }}
                                </a><br>
                                <a href="#" class="m-widget2__link m-link">
                                Tratante: 

                                </a>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
     </div>
   </div>
 </div>
</template>

<script>
export default {

    data() {
        return {
            events: [],
            diagnoses: [],
            urgencies: [],
            treatments: [],
            isFetching: true
        }
    },

    mounted() {
        this.loadData();
    },

    methods: {

        loadData: async function() {
            await axios.get('/pacientes/request-json/agenda/validarAsistencia/eventos').then(res => {
                this.events = res.data;
                this.diagnoses = [];
                this.urgencies = [];
                this.treatments = [];
                this.getDetails();
                this.getDelayColor();
                this.getConcurrence();
                vm.$nextTick(function () {
                    $('[data-toggle="m-tooltip"]').tooltip();
                });
                console.log('end LoadData');
            });
        },

        getDetails: function() {
            console.log('cargando');
            this.events.forEach(event => {
                axios.get('/pacientes/request-json/agenda/validarAsistencia/eventos/' + event.id).then(res => {
                    event.details = res.data;
                    console.log(res.data);
                });
            });
            this.distributeEvents();
            console.log('montado');
        },    

        distributeEvents: function() {
            this.events.forEach(event => {
                if ( event.event.event_type == "diagnosis" )
                {
                    this.diagnoses.push(event);
                }
                else if ( event.event.event_type == "urgency" )
                {
                    this.urgencies.push(event);
                }    
                else if ( event.event.event_type == "treatment" )
                {
                    this.treatments.push(event);
                }
            });
            this.isFetching = false;
        },

        getDelayColor: function() {
            this.events.forEach(event => {
                do something...
            });
        },

        getConcurrence: function() {
            this.events.forEach(event => {                    
                do something...
            });
        },

        diffMinutes: function(started_at) {
            do something...
        }

    }

}

采纳答案by kamatheuska

You aren't handling Promises properly, so they keep getting unresolved. You can use async, await, although I prefer myself using plain Promise Objects:

您没有正确处理 Promises,因此它们一直未解决。你可以使用async, await,虽然我更喜欢使用普通的Promise Objects

getDetails()is another story. You are making a loop, and forEachloop you are sending an axiosrequest. You could have to store each Promisereturned by each axioscall in an array, to call then Promise.all.

getDetails()是另一个故事。您正在制作一个循环,并forEach循环发送一个axios请求。您可能必须将每个axios调用返回的每个Promise存储在一个数组中,然后调用Promise.all

    getDetails: function() {
        let url = '/pacientes/request-json/agenda/validarAsistencia/eventos/';
        console.log('loading');
        let promisedEvents = [];

        this.events.forEach(event => {
            promisedEvents.push(axios.get(url + event.id))
        });

        return Promise.all(promisedEvents)
    },

After that I would do something like this:

之后我会做这样的事情:

    loadData: function() {
        axios.get('/pacientes/request-json/agenda/validarAsistencia/eventos')
            .then(res => {
                this.events = res.data;
                this.getDelayColor() // sync operation; no need to be returned
                return this.getDetails(); // Return the promise(s)
            })
            .then((res) => {
                // do something with the response from your array of Promises
            })
            .then(anotherPromise) // You can also return a promise like this 
            .catch(handleError) // Very important to handle your error!!
        });
    },

I am not saying this is the best way to achieve what you may want, but that it is one way to make your code to work. Important here is that you need to learn about Promises.

我并不是说这是实现您可能想要的最佳方式,而是说这是使您的代码工作的一种方式。这里重要的是你需要学习 Promises。

回答by Adi Darachi

To prevent the component from rendering before the data have returned you could:

为了防止组件在数据返回之前呈现,您可以:

  1. add a "isFetching" property to the data and set it to "true"

  2. in the fetch callback, set isFetching to "false"

  1. 向数据添加“isFetching”属性并将其设置为“true”

  2. 在 fetch 回调中,将 isFetching 设置为“false”

3.add v-if="!isFetching" to the wrapper of the component

3.将 v-if="!isFetching" 添加到组件的包装器中

回答by Pablo Araya

The Solution:

解决方案:

Thanks you guys !

谢谢你们!

         loadData: function() {
            axios.get('/pacientes/request-json/agenda/validarAsistencia/eventos')
                .then(res => {
                    this.events = res.data;
                    this.getDelayColor() // sync operation; no need to be returned
                    this.getConcurrence();
                    vm.$nextTick(function () {
                        $('[data-toggle="m-tooltip"]').tooltip();
                    });
                    return this.getDetails(); // Return the promise(s)
                })
                .then((res) => {
                    console.log(res.length);
                    for (var i = 0; i < res.length; i++) {
                        this.events[i].details = res[i].data;
                    }
                    this.distributeEvents();
                    console.log('end LoadData');
                })
                .catch(error => {
                    console.log('error');
                })
        },

        getDetails: function() {
            let url = '/pacientes/request-json/agenda/validarAsistencia/eventos/';
            let promisedEvents = [];

            this.events.forEach(event => {
                promisedEvents.push(axios.get(url + event.id))
            });

            return Promise.all(promisedEvents)
        },