vue.js - utilizar - ¿Cómo configurar un estado centralizado para un mapa mapbox en Vuex?
vuex modulos (1)
Acabo de empezar a usar vuex con vue. Sí (más o menos) entiendo los documentos. Tengo un problema específico para el cual no estoy seguro de si debo usar vuex y, si es así, cómo hacerlo.
Tengo una aplicación en la que mapa (s) mapbox están omnipresentes en varios diseños y componentes, etc. Como haré varios componentes vue de archivo único pero estoy trabajando con una misma instancia de un mapa mapbox, creo que tiene sentido tener el mapbox mapa iniciado y administrado en la tienda vuex. Entonces, por ejemplo, cuando cambio el diseño del mapa o alguna otra cosa, se reflejará en todos los componentes.
Cuando continúo en esta dirección, me desconcierta un par de cosas:
- El mapa no es solo una variable / matriz, sino una instancia del mapa de la clase mapbox. Entonces, supongo que el estado inicial es un objeto vacío y luego debe inicializarse. ¿Correcto?
- La inicialización es asíncrona y solo puede ocurrir después de que se cargue la página, supongo. ¡¿Por qué mi código a continuación no funciona ?!
Intenté seguir:
Hizo un módulo mapboxmap, con
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
}
Y como componente:
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>
Lo cual no funciona. Cualquier sugerencia sobre el enfoque de la solución y la forma específica de hacerlo es muy apreciada.
Aparece un mensaje de error en el navegador:
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
EDITAR: Después de cambiar a this.myMapForView
de this.computed.myMapForView
recibí el siguiente mensaje de error en el navegador:
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
Me parece que es new mapboxgl.Map()
es una función asincrónica y en vuex Las acciones pueden contener operaciones asincrónicas arbitrarias, no mutaciones ni mutaciones . las funciones del controlador de mutación deben ser sincrónicas.
Entonces deberías hacer un new mapboxgl.Map()
en acciones como las siguientes:
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
}
Editar :
Dado que las interacciones de su mouse están causando cambios en el estado, puede tener una propiedad calculada en su instancia vue con getter y setter , como por ejemplo:
computed: {
myMapForView: {
// getter
get: function () {
return this.$store.state. myMap
},
// setter
set: function (newMap) {
this.$store.commit(''loadMap'', newMap)
}
}
}
Working Fiddle: http://jsfiddle.net/aucqteLn/
También verifique: la tienda Vuex con "strict: true" no funciona