Vuejs:从商店加载 topojson 并使用 d3 绘图
Vuejs: loading topojson from store and plot with d3
我遇到的问题与这个问题类似:
首先,我想将一些静态 topojson 文件加载到商店中。这发生在 main.js 中主 vue 实例的挂载上:
new Vue({
...
mounted () {
this.$store.dispatch('topojsonStore/loadMunicipalityTopo',
'static/topojson_data/gem_2014.topojson')
}
})
这可以毫无问题地加载到商店中。在我想要可视化这些数据的组件中,我可以很好地从商店访问这些数据:
computed: {
getMunicipalityTopo () {
return this.$store.getters['topojsonStore/getMunicipalityTopo']
}
}
我将绘图功能放在组件中的一个方法下:
methods: {
plotMunicipalities () {
var width = 650,
height = 770
var path = d3.geoPath()
.projection(null) // TODO: fix projections
var svg = d3.select('#map').append('svg')
.attr('width', width)
.attr('height', height)
// Load topojson from store
let topoJsonData = this.getMunicipalityTopo
svg.append('path')
.attr('class', 'municipalities')
.datum(topoJsonData)
.attr('d', path)
}
如果我将其附加到模板中的点击事件,效果很好,如下所示:
<button @click="plotMunicipalities()">Plot municipalities</button>
但是,我想在加载页面时自动绘制这些东西,而不是在单击事件之后。这是我 运行 进入异步问题的地方......
例如,将它放在组件中是行不通的,因为商店中的数据仍未加载:
mounted () {
this.plotMunicipalities()
}
我应该怎么走?如何在加载商店中的数据时触发该功能?稍后我应该提到,将加载不同的层。某些层将无法由用户更改,但对于该特定层,用户可以更改它。我应该为这些不同的图层使用不同的工作流程吗?
一种方法是通过创建一个空的 vue 实例来设置全局事件总线
var EventBus = new Vue({});
然后让你的topojsonStore/loadMunicipalityTopo
行动return成为这样的承诺:
actions: {
topojsonStore/loadMunicipalityTopo: ({commit}) => {
return new Promise((resolve, reject) => {
commit(...);
resolve();
});
}
}
然后分派操作,以便您可以使用成功回调并发出如下事件:
new Vue({
...
mounted () {
this.$store.dispatch('topojsonStore/loadMunicipalityTopo',
'static/topojson_data/gem_2014.topojson').then(() => {
EventBus.$emit('store-json-loaded');
})
}
})
现在,在要绘制的组件的已创建挂钩中设置一个事件侦听器,如下所示:
created(){
EventBus.$on('store-json-loaded', () => {
this.plotMunicipalities();
});
}
虽然 Vamsi 的方法肯定有效,但我最终在组件中使用了一个 watcher:
watch: {
// Execute draw functions when data in store is done loading
getMunicipalityTopo: function () {
this.plotMunicipalities()
}
工作正常!
我遇到的问题与这个问题类似:
首先,我想将一些静态 topojson 文件加载到商店中。这发生在 main.js 中主 vue 实例的挂载上:
new Vue({
...
mounted () {
this.$store.dispatch('topojsonStore/loadMunicipalityTopo',
'static/topojson_data/gem_2014.topojson')
}
})
这可以毫无问题地加载到商店中。在我想要可视化这些数据的组件中,我可以很好地从商店访问这些数据:
computed: {
getMunicipalityTopo () {
return this.$store.getters['topojsonStore/getMunicipalityTopo']
}
}
我将绘图功能放在组件中的一个方法下:
methods: {
plotMunicipalities () {
var width = 650,
height = 770
var path = d3.geoPath()
.projection(null) // TODO: fix projections
var svg = d3.select('#map').append('svg')
.attr('width', width)
.attr('height', height)
// Load topojson from store
let topoJsonData = this.getMunicipalityTopo
svg.append('path')
.attr('class', 'municipalities')
.datum(topoJsonData)
.attr('d', path)
}
如果我将其附加到模板中的点击事件,效果很好,如下所示:
<button @click="plotMunicipalities()">Plot municipalities</button>
但是,我想在加载页面时自动绘制这些东西,而不是在单击事件之后。这是我 运行 进入异步问题的地方...... 例如,将它放在组件中是行不通的,因为商店中的数据仍未加载:
mounted () {
this.plotMunicipalities()
}
我应该怎么走?如何在加载商店中的数据时触发该功能?稍后我应该提到,将加载不同的层。某些层将无法由用户更改,但对于该特定层,用户可以更改它。我应该为这些不同的图层使用不同的工作流程吗?
一种方法是通过创建一个空的 vue 实例来设置全局事件总线
var EventBus = new Vue({});
然后让你的topojsonStore/loadMunicipalityTopo
行动return成为这样的承诺:
actions: {
topojsonStore/loadMunicipalityTopo: ({commit}) => {
return new Promise((resolve, reject) => {
commit(...);
resolve();
});
}
}
然后分派操作,以便您可以使用成功回调并发出如下事件:
new Vue({
...
mounted () {
this.$store.dispatch('topojsonStore/loadMunicipalityTopo',
'static/topojson_data/gem_2014.topojson').then(() => {
EventBus.$emit('store-json-loaded');
})
}
})
现在,在要绘制的组件的已创建挂钩中设置一个事件侦听器,如下所示:
created(){
EventBus.$on('store-json-loaded', () => {
this.plotMunicipalities();
});
}
虽然 Vamsi 的方法肯定有效,但我最终在组件中使用了一个 watcher:
watch: {
// Execute draw functions when data in store is done loading
getMunicipalityTopo: function () {
this.plotMunicipalities()
}
工作正常!