How to configure the centralized state of a map card in Vuex?

I just started using vuex with vue. I (roughly) understand the documents. I have a specific problem for which I am not sure whether to use vuex, and if so, how to do it.

I have an application in which mapbox (s) mapbox are ubiquitous in various layouts and components, etc. Since I will create several separate VUE components, but I work with the same copy of the cardboard card, I think it makes sense to create a memory card and run it in the vuex repository. So, for example, when I change the layout of a map or something else, it will be reflected in all components.

When I continue in this direction, I am puzzled by several things:

  • A map is not just a variable / array, but an instance of a map of map classes. Therefore, I assume that the initial state is an empty object, and then it should be initialized. Right?
  • Initialization is asynchronous and can only happen after the page loads. Perhaps that is why my code below does not work!

I tried the following:

Created a mapboxmap module, with

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 } 

And as a component:

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> 

What does not work. Any suggestions for a solution approach and a specific way to do this are greatly appreciated.

The error message I get in the browser:

 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 

EDIT: After switching to this.myMapForView from this.computed.myMapForView , I got an error in the browser:

 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 
+5
source share
1 answer

It seems to me that new mapboxgl.Map() is an asynchronous function and in vuex Actions can contain arbitrary asynchronous operations, and not mutations not from mutations . mutation processor functions must be synchronous.

So you should do new mapboxgl.Map() in the following steps:

 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 } 

Edit

Given that mouse interaction causes a state change, you can get the computed property in your vue instance with getter and setter , as shown below:

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

Working script: http://jsfiddle.net/aucqteLn/

Also check: Vuex store with "strict: true" does not work

+3
source

Source: https://habr.com/ru/post/1261801/


All Articles