Реквизиты дочерних компонентов VueJs не обновляются мгновенно

У меня есть настройка родительского/дочернего компонентов, где родитель загружает данные с сервера и передает их дочерним элементам через реквизиты. В дочернем я хотел бы создать экземпляр календаря jQuery с некоторыми данными, которые он получает от родителя.

Чтобы дождаться данных перед настройкой календаря, я транслирую событие в родительском элементе, в котором у меня есть настройка прослушивателя событий для дочернего элемента.

Слушатель запускается в дочернем элементе, но если я this.$log('theProp'), то он undefined. Тем не менее, если я проверяю компоненты с помощью VueJs devtools, между ними существует родительское/дочернее отношение, и ребенок получает поддержку в то же время.

Предел определяется для ребенка как динамический prop :the-prop="theProp". Поскольку ребенок действительно получает опору в конце, я предполагаю, что моя настройка верна, но, похоже, какая-то задержка. Родитель устанавливает реквизит в функции возврата вызова ajax и снова: он работает, просто с небольшой задержкой. Кажется, что.

Я также попробовал зарегистрировать прослушиватель watch на опоре в дочернем элементе, чтобы я мог настроить календарь и убедиться, что там есть опора. Тем не менее, прослушиватель часов срабатывает, но this.$log('theProp') по-прежнему undefined.

Если я передаю данные вместе с широковещательным вызовом, например this.$broadcast('dataLoaded', theData), ребенок получает его просто отлично. Но это кажется неправильным делать это таким образом, поскольку я в основном создаю свой собственный обработчик.

Я не отправляю какой-либо код, потому что компоненты довольно большие, и VueJs devtools говорят мне, что ситуация с родителем/ребенком работает.

Мне не хватает информации? Есть ли небольшая задержка между установкой значения в родительском и получающем его ребенке? Каким будет подходящий способ дождаться родительских данных у ребенка?

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

Спасибо.

изменить 1: здесь jsfiddle: https://jsfiddle.net/dr3djo0u/1/ Кажется, он подтверждает, что данные недоступны сразу после трансляции. Тем не менее, наблюдатель работает, хотя я мог почти поклясться, что иногда this.$log('someData') возвращал undefined, когда я настраивал этот тестовый файл.

Но я думаю, что моя проблема может быть где-то в другом месте, я посмотрю сегодня вечером, теперь у меня нет проекта.

edit 2: выполнил еще несколько тестов. Моя проблема заключалась в том, что а) прослушиватели событий, похоже, не получают данные мгновенно, и б) я также пытался запустить календарь в обратном вызове route.data, если someData уже был (например, при поступлении с родителя), но это обратный вызов маршрута вызывается до того, как компонент готов, поэтому он тоже не работает.

Мое решение теперь следующее:

// works when the child route is loaded directly and parent finishes loading someData
watch: {
    someData() {
        this.initCalendar();
    }
},

// works when navigating from parent (data already loaded)
ready() {
    if (this.someData && this.someData.length) {
        this.initCalendar()
    }
}

Ответ 1

Насколько я знаю, вам не нужны события для передачи данных от родителя к ребенку.

Все, что вам нужно, в дочернем компоненте: props: ['theProp']

И при использовании дочернего компонента в родительском: <child :theProp="someData"></child>

Теперь, где бы вы ни изменяли someData в родительском someData, дочерний компонент будет реагировать соответствующим образом.

Вам не нужны события, вам не нужно "смотреть", вам не нужно "готово".


Например: после вызова AJAX в родительском "ready" вы загружаете некоторые данные:

// at the parent component

data: function () {
  return {
    someData: {}
  }
},

ready: function () {
  var vm = this;
  $.get(url, function(response) {
    vm.someData = response;
  });
}

Теперь вам не нужно больше ничего передавать данные ребенку. Это уже у ребенка как theProp !

Что вам действительно нужно сделать, так это иметь в дочернем theProp нечто, реагирующее на изменения данных, в своем собственном theProp.

Либо в интерфейсе:

<div v-if="theProp.id > 0">
  Loaded!
</div>

Или в коде JavaScript:

// at the child component

computed: {
  // using a computed property based on theProp value
  awesomeDate: function() {
    if (!this.theProp || (this.theProp.length === 0)) {
      return false;
    }
    if (!this.initialized) {
      this.initCalendar();
    }
    return this.theProp.someThing;
  }
}

Обновление 1

В родителе вы также можете сделать дочерний объект условно:

<child v-if="dataLoaded" :theProp="someData"></child>

Установите для dataLoaded значение true, только если данные доступны.

Обновление 2

Или, возможно, ваша проблема связана с предупреждением об обнаружении изменений

Может быть, вы создаете новое свойство в объекте...

vm.someObject.someProperty = someValue

... когда ты должен сделать...

vm.$set('someObject.someProperty', someValue)

... среди других "предостережений".

Обновление 3

В VueJS 2 вы не ограничены шаблонами. Вы можете использовать функцию рендеринга и кодировать наиболее сложную логику рендеринга.

Обновление 4 (относительно OP edit 2)

Может быть, вы можете упасть ready и использовать immediate вариант, так что ваша инициализация в одном месте:

watch: {
  someData: {
    handler: function (someData) {
      // check someData and eventually call
      this.initCalendar();
    },
    immediate: true
  }
}

Ответ 2

решение (тестирование в порядке)

В дочернем компоненте, использующем только данные props, нет необходимости переназначать значения props data, это приведет к ошибке обновления!

vue дочерний компонент реквизит обновление ошибка и решение

enter image description here

https://forum.vuejs.org/t/child-component-is-not-updated-when-parent-component-model-changes/18283?u=xgqfrms