Страница Vuejs загружается до того, как запрос Axios вернет данные - PullRequest
0 голосов
/ 24 мая 2019

Задача

Я пытаюсь загрузить данные из моей базы данных, используя vuejs + axios в проекте Laravel. Локально я могу сделать запрос, используя axios, и он возвращает данные, назначает их переменным и затем выводит данные в DOM.

Когда я запускаю тот же код в производство, запрос axios выполняется немного дольше, но кажется, что он достаточно длинный, чтобы vuejs был готов, прежде чем будут возвращены все данные, что вызывает меня досадную ошибку 'undefined property', когда данные пытаются отображаться. Иногда эта ошибка сохраняется до 20+ обновлений до загрузки данных.

Как мне кажется, проблема

Так что я предполагаю, что при чтении axios не получает данные так быстро, как следовало бы, поэтому vuejs готов начать обслуживать данные, но у axios еще не было возможности их собрать, в результате чего undefined error

Что я прочитал и попробовал

Я читал, что использование операторов v-if для объектов, которые зависят от данных, должно решить эту проблему. Но это не так, все это делает это скрывает объект от просмотра, если данные отсутствуют. Например ...

HTML

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

JAVASCRIPT

<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. Я импортирую vue.js через CDN и использую его на странице в сценарии, как показано выше. Я не уверен, что такое использование приведет к таким ограничениям, я только выучил vue.js на базовом уровне, и это работает для компании и начальника ...

Ответы [ 3 ]

1 голос
/ 24 мая 2019

Вы можете добавить «загруженный» логический атрибут для решения этой проблемы. Например:

<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>
1 голос
/ 24 мая 2019

Отредактированный ответ, чтобы лучше объяснить, что я имею в виду.

Ваш код должен работать, независимо от того, требуется ли 1 или 10 секунд аксио для получения данных.Вам не нужно проверять v-if на user.name.VueJS имеет реактивность и обновляет представление при изменении свойства данных.

См. Этот пример кода.https://codepen.io/bergur/pen/VOXrzR

Здесь я жду 10 секунд, чтобы заполнить пользовательский объект

  1. {{user.name}} ничего не показывает, а затем Bergur
  2. {{computedName}} показывает неопределенное значение Hallgrímsson, потому что user.name не определено в течение 10 секунд.
  3. {{user.address.country}} выдаст ошибку (Невозможно прочитать свойство 'страна' из неопределенного), поскольку user.address недоступно в исходном объекте данных.

Таким образом, одно из решений состоит в том, чтобы изначально определить адрес в объекте данных

user: {
  address: {}
}

Я хочу сказать, что ваш исходный код должен работать (при рендеринге),Неопределенные ошибки появляются, когда

a) Вы используете это свойство name в своем приложении vue, например, user.name, когда свойство name отсутствует.

или

b) Когда вы визуализируете свойство 2-го уровня, например, user.address.country, поскольку адрес не был изначально определен.

0 голосов
/ 11 июля 2019

С помощью debounce 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];
    },
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...