开发者问题收集

Vue JS 在渲染之前等待数据

2019-01-03
62302

几周以来,我一直被 VueJS 渲染数据的问题所困扰。

我正在做的是进行一些 axios 调用(一个在另一个里面)。我的问题是数据在调用完成之前就被渲染了,所以视图没有显示任何内容。

我看到了一些执行“await”和“Async 调用”的代码,但似乎没有什么能解决我的问题。

这里也有类似的东西 获取组件在渲染之前等待异步数据 但也没有用

这是我的代码:

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

        }

    }
3个回答

为了防止组件在数据返回之前进行渲染,您可以:

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

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

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

Adi Darachi
2019-01-03

您没有正确处理 Promises,因此它们一直处于 未解决 状态。您可以使用 asyncawait ,尽管我更喜欢使用普通的 Promise 对象

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

之后,我会做这样的事情:

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!!
        });
    },

我并不是说这是实现您想要的最佳方式,但它是让您的代码正常工作的一种方法。这里重要的是您需要了解 Promises。

nicoramirezdev
2019-01-03

解决方案:

谢谢大家!

         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)
        },
Pablo Araya
2019-01-03