使用带有Vue的Leaflet了解双向数据绑定和范围

时间:2018-02-05 14:54:26

标签: javascript vue.js leaflet

我以前用React方式处理这个问题,单向数据绑定和状态,所以我很难用Vue来思考它。

我有一张地图,根据新闻故事的lat / lng呈现点数。当用户更改选择的值时,地图上的点会更新。当用户点击某个点时,会打开一个弹出窗口,其中包含指向该故事的链接。但是,我不能让这两个功能一起工作。

这是我的Vue模板:

<div class="row">
  <div id="map" class="map"></div>
</div>

<select v-model="selectedMonth">
  <option disabled value="">Please select one</option>
  <option>January 2018</option>
  <option>December 2017</option>
  <option>November 2017</option>
  <option>October 2017</option>
</select>
<button v-on:click="reset">Reset all</button>

<div class="row">
  <div class="col col-xs-12 col-sm-6 col-md-3 col-lg-3"
       v-for="(story, index) in displayedStories">
    <img v-bind:src="story.img_src" />
    <br />
    <a v-bind:href="story.url" target="_blank">{{ story.card_title }}</a>
    <p>{{ story.published }}</p>
  </div>
</div>

和JS:

export default {
  name: 'app',
  data() {
    return {
      leafleftMap: null,
      tileLayer: null,
      markers: [],
      allStories: [],
      selectedMonth: null,
    }
  },
  mounted() {
    this.getNodes()
    this.initMap()
  },
  computed: {
    displayedStories() {
      const displayedStories = this.selectedMonth
        ? dateFilter(this.selectedMonth, this.allStories)
        : this.allStories

      if (this.leafleftMap) {
        /* remove old markers layer */
        this.leafleftMap.removeLayer(this.markers)

        /* create a new batch of markers */
        const markers = displayedStories.map(story => L.marker(story.coords)
          .bindPopup(mapLink(story))
    )
        const storyMarkers = L.layerGroup(markers)

        /* add current markers to app state and add to map */
        this.markers = storyMarkers
        this.leafleftMap.addLayer(storyMarkers)
        this.changedMonth = this.selectedMonth
      }
      return displayedStories
    },
  },

  methods: {
    getNodes() { /* make api request */ }
    initMap () { /* initialize map with */ }
  },
}

问题在于行this.leafleftMap.removeLayer(this.markers)。当它出现时,标记会使用选择按钮进行渲染和更改,但弹出窗口不起作用。当我删除该行时,弹出窗口可以正常工作,但是当选择更改时,地图将无法更新。

我尝试在select:

中添加自定义指令
<select v-model="selectedMonth" v-updateMonth>

希望在JavaScript制定时关注:

directives: {
  updateMonth: {
    update: function(el, binding, vnode) {
      console.log('select updated')
      vnode.context.leafleftMap.removeLayer(vnode.context.markers)
    }
  }
},

但是只要页面上的任何内容发生变化,就会调用该指令,而不仅仅是在我更新select时。

我只是在更改选择时尝试调用函数(删除标记),但似乎无法在Vue中使用它。它想要在每次更新时调用每个函数。

1 个答案:

答案 0 :(得分:0)

我能够用@change来解决这个问题,我想我更了解何时在Vue中使用computed。

首先,我将大量更新逻辑移出计算:

computed: {
  displayedStories() {
    return this.selectedMonth
      ? dateFilter(this.selectedMonth, this.allStories)
      : this.allStories
  },
},

所以它只是返回一个数组。然后我在select:

中添加了一个监听器
<select v-model="selectedMonth" @change="updateStories()">

然后创建了一个处理该更改的新方法:

methods {
  updateStories() {
    const markers = displayedStories.map(story => L.marker(story.coords)
      .bindPopup(mapLink(story)))
    const storyMarkers = L.layerGroup(markers)
    this.markers = storyMarkers
    this.leafleftMap.addLayer(storyMarkers)
    this.changedMonth = this.selectedMonth
  },
},