尝试在 Vue + Vuex 项目中嵌入 Vega 图表时出现未捕获的错误
Uncaught error when trying to embed a Vega chart in Vue + Vuex project
我正在尝试在 Vue.js(与 vuex 一起用于状态管理)项目中使用 vega-embed。基本上,后端服务于 Vega json 对象,该对象由前端通过带有点击事件的 HTTP GET 请求获取。但是,我必须单击两次才能显示绘图,并且第一次单击事件总是会触发错误“Uncaught (in promise) TypeError: Cannot read property '$schema' of null
”。有人可以帮我调试吗?非常感谢。详情如下:
vue组件文件:
<template>
<button @click.native="fetchCars(); displayVegaPlot()">fetch cars</button>
<div id="vega-example"></div>
</template>
<script>
import {default as vegaEmbed} from 'vega-embed'
import {
mapState
} from 'vuex'
export default {
name: 'VegaExample',
props: {
component_msg: String
},
methods: {
fetchCars () {
this.$store.dispatch('fetchCars')
},
displayVegaPlot () {
vegaEmbed('#vega-example', this.vega_cars, {actions: false})
}
},
computed: {
...mapState([
'vega_cars'
])
}
}
</script>
...和商店 js 文件:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
strict: true,
state: {
error: '',
vega_cars: null
},
mutations: {
SET_CARS: (state, cars) => {
state.vega_cars = cars
},
SET_ERROR: (state, error) => {
state.error = error
}
}
actions: {
fetchCars: (context) => {
axios.get(`vega_cars`)
.then(response => context.commit('SET_CARS', response.data))
.catch(error => context.commit('SET_ERROR', error))
}
}
非常感谢@TommyF 的评论,在阅读了一些文档后我想我找到了解决方案(显然作为网络应用程序开发的新手 Vue
我不知道 Vue
提供特殊的 watch
设施)。因此,在组件 Vue 文件中,不用声明方法 displayVegaPlot
来强制调用,只要 vega_cars
更改值,就可以设置 watch
来显示 Vega 图:
watch: {
vega_cars: (spec) => {
console.log('$store.state.vega_cars changed value')
if (spec) {
vegaEmbed('#vega-example', spec, {actions: false})
}
}
}
当然 ...mapState(['vega_cars'])
需要放在 computed
.
我正在尝试在 Vue.js(与 vuex 一起用于状态管理)项目中使用 vega-embed。基本上,后端服务于 Vega json 对象,该对象由前端通过带有点击事件的 HTTP GET 请求获取。但是,我必须单击两次才能显示绘图,并且第一次单击事件总是会触发错误“Uncaught (in promise) TypeError: Cannot read property '$schema' of null
”。有人可以帮我调试吗?非常感谢。详情如下:
vue组件文件:
<template>
<button @click.native="fetchCars(); displayVegaPlot()">fetch cars</button>
<div id="vega-example"></div>
</template>
<script>
import {default as vegaEmbed} from 'vega-embed'
import {
mapState
} from 'vuex'
export default {
name: 'VegaExample',
props: {
component_msg: String
},
methods: {
fetchCars () {
this.$store.dispatch('fetchCars')
},
displayVegaPlot () {
vegaEmbed('#vega-example', this.vega_cars, {actions: false})
}
},
computed: {
...mapState([
'vega_cars'
])
}
}
</script>
...和商店 js 文件:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
strict: true,
state: {
error: '',
vega_cars: null
},
mutations: {
SET_CARS: (state, cars) => {
state.vega_cars = cars
},
SET_ERROR: (state, error) => {
state.error = error
}
}
actions: {
fetchCars: (context) => {
axios.get(`vega_cars`)
.then(response => context.commit('SET_CARS', response.data))
.catch(error => context.commit('SET_ERROR', error))
}
}
非常感谢@TommyF 的评论,在阅读了一些文档后我想我找到了解决方案(显然作为网络应用程序开发的新手 Vue
我不知道 Vue
提供特殊的 watch
设施)。因此,在组件 Vue 文件中,不用声明方法 displayVegaPlot
来强制调用,只要 vega_cars
更改值,就可以设置 watch
来显示 Vega 图:
watch: {
vega_cars: (spec) => {
console.log('$store.state.vega_cars changed value')
if (spec) {
vegaEmbed('#vega-example', spec, {actions: false})
}
}
}
当然 ...mapState(['vega_cars'])
需要放在 computed
.