Vue Nexttick для карты - PullRequest
       9

Vue Nexttick для карты

0 голосов
/ 05 ноября 2019

У меня есть <div id="map" />

У меня есть смонтированный метод, в котором я инициализирую карту.

mounted(){
 this.map = L.map(this.mapId, { preferCanvas: true }).setView(
  [this.initialLatitudeOriginalPoint, this.intiialLongitudeOriginalPoint],
        3
 )
L.tileLayer(
        tileconfig + '?access_token=' + key
        { maxZoom: 25, id: 'mapbox.streets' }
      ).addTo(this.map)
}

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

markers:{
      handler(newVal, oldVal){
        this.showMarkers()
      },
      immediate: true
    },

Вопрос - Похоже, watcher вызывается первым. до монтированияТогда функция showMarkers выдает ошибку, так как карта не будет определена, потому что watcher был получен первым до mounted. Мне действительно нужна немедленная истина для этого наблюдателя. Могу ли я узнать, что пока карта не определена, наблюдатель должен подождать?

Что я думаю о : я думаю об использовании nextTick. но я не понимаю один момент по этому поводу. Если я напишу это. $ NextTick в функции-обработчике моего наблюдателя, когда будет вызван этот обратный вызов nextTick? после того, как дом был обновлен в этом конкретном компоненте или даже в родителей и родителей родителей? если это не волнует текущий компонент, тогда nextTick может быть немного неправильным в моем случае. Я просто хочу понять эту последнюю вещь о nextTick. какая-нибудь подсказка?

1 Ответ

1 голос
/ 06 ноября 2019

Во-первых, вы правы, что immediate вызовет срабатывание watch перед установкой компонента. Роль watch заключается прежде всего в обновлении свойств на основе других свойств. Поэтому он будет ожидать инициализации всех основных свойств (реквизиты, данные и т. Д.), Но предполагает, что для рендеринга потребуется вывод watch для правильной рендеринга. В вашем случае это не так.

Я бы написал так:

mounted () {
  // ... map stuff ...

  this.showMarkers()
},

watch: {
  markers: 'showMarkers'
}

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

Однако вам не нужно делать это таким образом. Вы можете сделать это, используя immediate и nextTick, как предложено в вопросе.

Поэтому ключевым моментом является понимание, когда именно вызывается nextTick.

Если зависимость отрисовкиИзменения Vue не будет повторно визуализировать компонент немедленно. Вместо этого он добавляется в очередь. Как только весь ваш другой код завершит работу, Vue обработает эту очередь. Это сложнее, чем кажется, поскольку различные компоненты в иерархии родитель / потомок могут нуждаться в обновлении. Обновление родительского элемента может привести к тому, что дочерний элемент больше не будет существовать.

После обработки очереди и обновления DOM Vue будет вызывать любые обратные вызовы nextTick. Любые дальнейшие изменения, которые происходят внутри обратного вызова, будут добавлены в новую очередь рендеринга.

Здесь следует отметить пару ключевых моментов.

  1. Хотя Vue, возможно, обновил DOMбраузер фактически не будет рисовать все новые узлы, пока не завершится код JavaScript. Это включает в себя любые nextTick обратные вызовы. Поэтому, если nextTick инициирует дальнейшие обновления, пользователь не увидит промежуточное состояние страницы.
  2. Все это предполагает, что Vue отслеживает обновления и выполняет рендеринг. Если вы выполняете рендеринг вне Vue, как вы делаете это с помощью Leaflet, то Vue не может сделать столько, чтобы помочь вам.

Итак, давайте рассмотрим следующее:

markers:{
  async handler(newVal, oldVal){
    await this.$nextTick()  
    this.showMarkers()
  },
  immediate: true
},

Я использовал async / await здесь, вместо того, чтобы передавать обратный вызов, но конечный результат тот же.

Когда handler вызывается в первый раз, это происходит до того, как компонент отобразил,$nextTick будет вызван после завершения рендеринга (включая другие компоненты). Пока другие компоненты не предполагают, что маркеры уже существуют, это не должно быть проблемой, они все равно будут созданы до того, как пользователь что-либо увидит.

Когда markers впоследствии изменится, это может на самом деле не существоватьвызвать любой рендеринг в Vue. Если вы не используете markers где-то в одном из ваших шаблонов, это не будет зависимостью от рендеринга, поэтому новый рендеринг не будет запущен. Это не обязательно проблема, так как $nextTick все равно будет работать, даже если Vue не будет ничего визуализировать.

...