vue nexttick获取地图

时间:2019-11-05 08:36:50

标签: javascript vue.js vuejs2 vue-component

我有一个<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函数将引发错误,因为将不会定义映射,因为watchermounted之前排在第一位。我真的需要那个观察员立即采取行动。我有什么办法知道,在未定义map之前,观察者应该等待吗?

我的想法:我考虑使用nextTick。但我对此一无所知。如果我在观察者的处理函数中编写this。$ nextTick,那么何时调用nextTick回调? dom在此特定组件或什至是父母的父母中更新之后?如果它不在乎当前组件,那么在我的情况下,nextTick可能有点错误。我只想了解有关nextTick的最后一件事。有任何线索吗?

1 个答案:

答案 0 :(得分:1)

首先,您正确地认为immediate将导致watch在安装组件之前被触发。 watch的作用主要是根据其他属性对属性进行更新。因此,它将等待所有基本属性(属性,数据等)被初始化,但假定渲染需要watch的输出才能正确渲染。在您的情况下,这是不正确的。

我写这个的方式是:

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

  this.showMarkers()
},

watch: {
  markers: 'showMarkers'
}

如果其中需要一个nextTick,我倾向于在showMarkers内部进行,而不是使其成为呼叫者的问题。

但是,您不必这样做。您可以按照问题中的建议使用immediatenextTick来做到这一点。

所以关键是要了解何时准确调用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不需要渲染。