vue.js vue-chartjs 图表在替换、更新 chartData 等时不会更新
我正在尝试使用 vue-chartjs 制作 vue。我已遵循与在更新 chartData prop 时重新渲染图表相关的所有文档。我的图表仅在我调整浏览器窗口大小后才会更新。
我的 parenttestchart.vue 文件:
<template>
<div>
<h1>Chart datacollection update test</h1>
<p>This component demonstrates fetching data from the server.</p>
<p v-if="!datacollection"><em>Loading...</em></p>
<b-form-select
v-model="testthingSelect.selected"
text="Select testthing"
variant="primary"
:options="testthingSelect.options"
:on-change="changetestthing"
class="m-md-2">
</b-form-select>
<test-chart v-cloak :chart-data="datacollection" :chart-option="options"></test-chart>
</div>
</template>
<script>
import TestChart from './TestChart'
export default {
components: {
TestChart
},
data() {
return {
yAxisValues: [],
datacollection: {},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: false
},
gridLines: {
display: true
}
}],
xAxes: [{
type: "date",
display:true,
gridLines: {
display: false
}
}]
},
legend: {
display: true
},
responsive: true,
maintainAspectRatio: false
},
testthingSelect: {
selected: "EIA/COAL",
disabled: false,
readonly: false,
visible: true,
color: "",
options: [
{
value: null,
text: 'Select a testthing'
},
{
value: "item1",
text: "item1"
},
{
value: "item1",
text: "item1"
},
{
value: "item1",
text: "item1"
}
]
}
}
},
methods: {
changetestthing: async function () {
try {
let response = await this.$http.get(url for my data);
this.datacollection.datasets = [];
this.datacollection.labels = [];
...required data transformations
this.$set(this.datacollection, "labels", labels);
this.$set(this.datacollection, "datasets", datasets);
// this.datacollection.labels = labels;
// this.datacollection.datasets = datasets;
} catch (error) {
console.log(error)
}
}
},
watch: {
'commoditySelect.selected': function () { this.changeCommodity(); }
},
async created() {
// ES2017 async/await syntax via babel-plugin-transform-async-to-generator
// TypeScript can also transpile async/await down to ES5
try {
let response = await this.$http.get(url for my data);
this.datacollection.datasets = [];
this.datacollection.labels = [];
...required data transformations
this.$set(this.datacollection, "labels", labels);
this.$set(this.datacollection, "datasets", datasets);
// this.datacollection.labels = labels;
// this.datacollection.datasets = datasets;
} catch (error) {
console.log(error)
}
} catch (error) {
console.log(error)
}
}
}
我的 TestChart.vue 文件
<script>
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
//Exporting this so it can be used in other components
export default {
extends: Line,
mixins: [reactiveProp],
props: ['chartData', 'options'],
mounted() {
this.renderChart(this.chartData, this.options)
}
}
</script>
因此,这在选择和更改父 vue 中的数据集合方面是有效的。除非我调整窗口大小,否则图表不会重新渲染。当 parenttestchart.vue 最初加载时,我收到以下错误:'Uncaught TypeError: Cannot read property 'transition' of null'。但这似乎没有影响任何东西,因为调整窗口大小将渲染图表的初始显示。更新数据 changetestthing 方法确实会正确更新 datacollection (chartData),但除非我调整窗口大小,否则它不会重新渲染。
如何强制图表重新渲染?如何获取对父级中 TestChart 组件的引用??this.TestChart 未定义。我只是想知道如何获取引用,以防万一我可以从引用中手动调用“renderChart”。谢谢。
*** 更新
我能够通过以下修改来更新图表:
我从 changetestthing 方法中删除了以下几行:
this.datacollection.datasets = null;
this.datacollection.labels = null;
并将 datacollection 值赋值语句更改为:
this.datacollection = Object.assign({}, this.datacollection, { labels: labels, datasets: datasets });
我不能肯定地说这是最佳做法。根据 vue.js 文档 ( https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats )
new properties added to the object will not trigger changes. In such
cases, create a fresh object with properties from both the original
object and the mixin object
因此,我相信通过不将 datacollection.labels 和 .datasets 属性设置为 null,然后使用 Object.assign,可以触发更改。我仍然不确定为什么它们没有使用 mixins 或手动监视来触发。欢迎提出任何意见。
一种可行的方法是向图表添加一个观察器,
props: ['chartData', 'options'],
mounted () {
this.renderChart(this.chartData, this.options)
},
watch: {
'chartData' (to, from) {
this.renderChart(this.chartData, this.options)
}
},
查看示例 CodePen
编辑 - 观察器不起作用
您的代码和正常工作的 CodePen 之间的区别在于,CodePen 会改变传递到图表中的变量,因此它的观察器会做出反应。
您的代码会改变变量的
.datasets
属性 - 此引用存在一个已知问题:
Mixins 似乎不会触发图表 #44 的刷新
。
尝试用这个(两个地方)替换
this.datacollection.datasets = [];
this.datacollection.labels = [];
this.datacollection = { datasets: [], labels: [] };
Billy Jean 的最终注释对我有用 PIECHART.JS:
import {
Pie,
mixins
} from 'vue-chartjs'
const {
reactiveProp
} = mixins
export default Pie.extend({
mixins: [reactiveProp],
props: ['options'],
watch: {
'options': {
handler(newOption, oldOption) {
this._chart.destroy()
this.renderChart(this.chartData, this.options)
},
deep: true
}
},
mounted() {
this.renderChart(this.chartData, {responsive: true, maintainAspectRadio:
false})
}
})
这是我的 view.vue 文件中的内容:
let datasets = []
let colorlist = [ '#4e5fa4', '#5e5fa4', '#6e5fa4',
'#7e5fa4', '#8e5fa4', '#a08be4', '#b08bd4']
datasets.push({
label: this.data_by_city_label,
data: this.data_by_city_data,
fill: false,
backgroundColor: colorlist,
pointBorderWidth: 1,
borderWidth: 1,
pointRadius: 0
})
this.CityDatac = Object.assign({}, this.datasets, {labels: this.data_by_city_label, datasets: datasets})
有了这个,我可以将我的数据发送到 PIECHART js 并在我的 view.vue 中生成 如下:
<pie-chart-city :chartData="CityDatac" :width="300" :height="250"></pie-chart-city>
希望这对 VUE.js -> Vue-chartjs.js 中的任何人有所帮助
Alexis Poo 发布的代码为我指明了正确的方向。
就我而言,我需要稍微修改一下
watch
对象。
当选项更改时,尝试通过调用
this._chart.destroy()
来销毁图表时,我收到一条错误消息:
无法读取未定义的属性“destroy”
。
要解决此问题,我必须改为执行
this.$data._chart.destroy()
。
希望对您有所帮助。