Во-первых, вы правы, что immediate
вызовет срабатывание watch
перед установкой компонента. Роль watch
заключается прежде всего в обновлении свойств на основе других свойств. Поэтому он будет ожидать инициализации всех основных свойств (реквизиты, данные и т. Д.), Но предполагает, что для рендеринга потребуется вывод watch
для правильной рендеринга. В вашем случае это не так.
Я бы написал так:
mounted () {
// ... map stuff ...
this.showMarkers()
},
watch: {
markers: 'showMarkers'
}
Если там должен быть nextTick
, я бы хотел сделать эточто внутри showMarkers
вместо того, чтобы делать это проблемой вызывающего.
Однако вам не нужно делать это таким образом. Вы можете сделать это, используя immediate
и nextTick
, как предложено в вопросе.
Поэтому ключевым моментом является понимание, когда именно вызывается nextTick
.
Если зависимость отрисовкиИзменения Vue не будет повторно визуализировать компонент немедленно. Вместо этого он добавляется в очередь. Как только весь ваш другой код завершит работу, Vue обработает эту очередь. Это сложнее, чем кажется, поскольку различные компоненты в иерархии родитель / потомок могут нуждаться в обновлении. Обновление родительского элемента может привести к тому, что дочерний элемент больше не будет существовать.
После обработки очереди и обновления DOM Vue будет вызывать любые обратные вызовы nextTick
. Любые дальнейшие изменения, которые происходят внутри обратного вызова, будут добавлены в новую очередь рендеринга.
Здесь следует отметить пару ключевых моментов.
- Хотя Vue, возможно, обновил DOMбраузер фактически не будет рисовать все новые узлы, пока не завершится код JavaScript. Это включает в себя любые
nextTick
обратные вызовы. Поэтому, если nextTick
инициирует дальнейшие обновления, пользователь не увидит промежуточное состояние страницы. - Все это предполагает, что 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 не будет ничего визуализировать.