如何在Vuex中为地图集地图设置集中状态?

时间:2016-12-23 21:44:11

标签: vue.js vue-component mapbox-gl-js vuejs2 vuex

我刚开始使用vuex和vue。我(大致)理解文档。我有一个特定的问题,我不确定是否应该使用vuex,如果是的话,该怎么做。

我有一个应用程序,其中mapbox地图在各种布局和组件等中无所不在。因为我将制作几个vue单个文件组件但是正在使用一个相同的mapbox地图实例我认为这是有意义的在vuex存储中启动和管理地图框图。所以例如当我更改地图布局或其他内容时,它将反映在所有组件中。

当我继续朝着这个方向前进时,我对以下几点感到困惑:

  1. 地图不仅仅是一个变量/数组,而是一个mapbox类映射的实例。所以我认为初始状态是一个空对象然后需要初始化。正确的吗?
  2. 初始化是异步的,只能在页面加载后才会发生,我想。这可能就是为什么我的代码不能正常工作的原因!?
  3. 我试过以下:

    制作了一个带有

    的mapboxmap模块

    mapboxmap.js

    import simple from '../../components/simplestyle'
    let mapboxgl = require('mapbox-gl/dist/mapbox-gl.js')
    
    // initial state
    const state = {
      myMap: {},
      mapLoaded: false
    }
    
    const mutations = {
      loadMap (state, myMap) {
        state.myMap = myMap
        state.mapLoaded = true
      }
    }
    
    const actions = {
      loadMap (context) {
        'use strict'
        mapboxgl.accessToken = 'mysecretmapboxcode'
        let myMap = new mapboxgl.Map({
          container: 'map',
          style: simple,
          hash: true,
          center: [-74.0073, 40.7124],
          zoom: 16
        })
        context.commit('loadMap', myMap)
      }
    }
    
    export default {
      state,
      mutations,
      actions
    }
    

    作为组成部分:

    Maplayout.vue

    <template>
      <div>
        <div id='map' class='map'>
        </div>
      </div>
    </template>
    
    <script type='text/babel'>
    export default {
      mounted () {
        this.computed.myMapForView.set().then(() => this.computed.myMapForView.get())
      },
      computed: {
        myMapForView: {
          // getter
          get: function () {
            return this.$store.state.myMap
          },
          // setter
          set: function () {
            this.$store.dispatch('loadMap')
          }
        }
      }
    }
    </script>
    

    哪个不起作用。任何有关解决方案方法的建议和具体的方法都非常感谢。

    我在浏览器中收到错误消息:

    vue.runtime.common.js?d43f:433 TypeError: Cannot read property 'myMapForView' of undefined
        at VueComponent.mounted (eval at 162 (0.ce2d9bf….js:21), <anonymous>:8:18)
        at callHook (eval at <anonymous> (app.js:794), <anonymous>:2335:19)
        at Object.insert (eval at <anonymous> (app.js:794), <anonymous>:2525:5)
        at invokeInsertHook (eval at <anonymous> (app.js:794), <anonymous>:4352:28)
        at VueComponent.patch [as __patch__] (eval at <anonymous> (app.js:794), <anonymous>:4508:5)
        at VueComponent.Vue._update (eval at <anonymous> (app.js:794), <anonymous>:2222:19)
        at VueComponent.eval (eval at <anonymous> (app.js:794), <anonymous>:2189:10)
        at Watcher.get (eval at <anonymous> (app.js:794), <anonymous>:1652:27)
        at Watcher.run (eval at <anonymous> (app.js:794), <anonymous>:1721:22)
        at flushSchedulerQueue (eval at <anonymous> (app.js:794), <anonymous>:1539:13)
    logError @ vue.runtime.common.js?d43f:433
    

    编辑: 从this.myMapForView更改为this.computed.myMapForView后,我在浏览器中收到以下错误消息:

    vue.runtime.common.js?d43f:433 
    TypeError: Cannot read property 'set' of undefined
        at VueComponent.mounted (eval at 162 (0.85b2be9….js:21), <anonymous>:6:22)
        at callHook (eval at <anonymous> (app.js:794), <anonymous>:2335:19)
        at Object.insert (eval at <anonymous> (app.js:794), <anonymous>:2525:5)
        at invokeInsertHook (eval at <anonymous> (app.js:794), <anonymous>:4352:28)
        at VueComponent.patch [as __patch__] (eval at <anonymous> (app.js:794), <anonymous>:4508:5)
        at VueComponent.Vue._update (eval at <anonymous> (app.js:794), <anonymous>:2222:19)
        at VueComponent.eval (eval at <anonymous> (app.js:794), <anonymous>:2189:10)
        at Watcher.get (eval at <anonymous> (app.js:794), <anonymous>:1652:27)
        at Watcher.run (eval at <anonymous> (app.js:794), <anonymous>:1721:22)
        at flushSchedulerQueue (eval at <anonymous> (app.js:794), <anonymous>:1539:13)
    logError @ vue.runtime.common.js?d43f:433
    

1 个答案:

答案 0 :(得分:4)

在我看来,new mapboxgl.Map()是一个异步函数,而vuex Actions中可以包含任意异步操作,而不是来自mutations的突变。 变异处理函数必须是同步的。

因此,您应该在以下操作中执行new mapboxgl.Map()

import simple from '../../components/simplestyle'
let mapboxgl = require('mapbox-gl/dist/mapbox-gl.js')

// initial state
const state = {
  myMap: {},
  mapLoaded: false
}

const mutations = {
  loadMap (state, myMap) {
    state.myMap = myMap
  }
}

const actions = {
  loadMap (context) {
    'use strict'
    mapboxgl.accessToken = 'mysecretmapboxkey'
    var myMap = new mapboxgl.Map({
      container: 'map',
      style: simple,
      hash: true,
      center: [-74.0073, 40.7124],
      zoom: 16
    })
    context.commit('loadMap', myMap)
  }
}

export default {
  state,
  mutations,
  actions
}

修改

鉴于您的鼠标互动导致状态发生变化,您可以使用computed property在vue实例中设置getter and setter,如下所示:

computed: {
  myMapForView: {
    // getter
    get: function () {
      return this.$store.state. myMap
    },
    // setter
    set: function (newMap) {
      this.$store.commit('loadMap', newMap)
    }
  }
}

工作小提琴:http://jsfiddle.net/aucqteLn/

同时检查:Vuex store with "strict: true" does not work