Chart JS 不会使用 update() 方法动态更新新数据
Chart JS isn't dynamically updating with new data with update() method
我在我的 Nuxt JS 项目中使用 Chart JS 和 Vue Chart JS 包装器。出于某种原因,尽管有新数据,但我的图表没有更新新数据。我的图表设置有一个名为 LineChart.vue
的组件,以及一个名为 LineChart.js
的插件,位于我的 plugins
目录中。
我的组件看起来像:
<template>
<div>
<line-chart :chart-data="customChartData" class="data-chart"></line-chart>
</div>
</template>
<style>
.data-chart canvas {
width: 100% !important;
height: auto !important;
}
</style>
<script>
import LineChart from '~/plugins/LineChart.js'
export default {
components: {
LineChart
},
props: {
chartKey: {
type: Number,
default: 0
},
groupBy: {
type: String,
default: 'hourly'
},
labels: {
type: Array,
default: null
},
datasets: {
type: Array,
default: null
},
options: {
type: Object,
default: () => ({})
}
},
data () {
return {
customChartData: {}
}
},
mounted () {
this.fillData()
},
methods: {
/*
** Fill data
*/
fillData () {
const labelsToUse = []
const labels = this.labels
const first = labels[0]
const last = labels[labels.length - 1]
let diff = 0
for (const [index, label] of labels.entries()) {
const periodStart = this.$dayjs(Date.parse(first))
const periodFinish = this.$dayjs(Date.parse(last))
diff = periodFinish.diff(periodStart, 'day', true)
if (!diff) {
labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format('MMM Do'))
}
labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format(`${diff > 1 ? 'MMM Do' : 'HH:mm'}`))
}
this.customChartData = {
labels: labelsToUse,
datasets: this.datasets,
options: this.options
}
}
}
}
</script>
我的插件看起来像...
import { Line, mixins } from 'vue-chartjs'
import _ from 'lodash';
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
data () {
return {
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [{
gridLines: {
display: true,
color: '#eceaea'
},
}],
xAxes: [{
gridLines: {
display: false
},
ticks: {
autoSkip: true,
maxTicksLimit: window.innerWidth < 575 ? 2.1 : 4.1,
maxRotation: 0,
minRotation: 0
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 35
}
}
}
}
},
mounted () {
this.renderLineChart()
},
methods: {
/*
** Get chart options
*/
getChartOptions () {
return this.options
},
/*
** Render a line chart
*/
renderLineChart () {
const options = this.getChartOptions()
// this.chartdata is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.localData, options)
}
},
computed: {
localData: function() {
return this.chartData
}
},
watch: {
chartData: {
handler: function (val, oldVal) {
const options = this.getChartOptions()
const clone = _.cloneDeep(this.localData)
console.log(this.localData)
this._data._chart.update()
this.renderChart(clone, options)
},
deep: true
}
}
}
当我在我的插件的 watch 方法中记录 console.log(this.localData)
时,我没有看到我的 labels
更新了从 :labels="server[Object.keys(server)[0]].history.labels"
推送的新标签和数据在我调用折线图的网页内,我缺少什么?
调用我的图表组件的页面是:
<div class="col-span-12" v-for="(server, index) in servers" :key="index">
<div class="bg-white p-6 rounded-md">
<h3 class="text-md font-medium text-gray-900">{{ server[Object.keys(server)[0]].agent.agent }}</h3>
</div>
<hr v-if="server[Object.keys(server)[0]].history" />
<div v-if="server[Object.keys(server)[0]].history" class="bg-white p-6 rounded-md">
<h3 class="text-md font-medium text-gray-500 mb-3">Free memory</h3>
<div class="chart chart--generic">
<LineChart
:labels="server[Object.keys(server)[0]].history.labels"
:datasets="[{
fill: false,
borderWidth: 2.5,
pointBackgroundColor: '#fff',
borderColor: '#5046e5',
data: server[Object.keys(server)[0]].history.data,
}]"
/>
</div>
</div>
</div>
更新数组标签后,您可以尝试调用 fillData() 方法。
希望有用
我目前正在构建一个应用程序并使用 Nuxt 和 ApexCharts 并且遇到了非常相似的问题。我的数据正在更新,但我在图表中没有看到任何变化。我解决这个问题的方法是向我的图表组件添加一个 key
并手动强制它重新呈现。 Vue 使用 key
属性来跟踪已更改和未更改的内容。通过提供一个新的,我们强制重新渲染。
我的解决方案的一个例子是,
<apexcharts
v-if="chartOptions"
:id="chartId"
:key="key"
class="am2-utility-chart"
:class="[isCategoryType ? 'marginLeft' : '']"
:ref="chartId"
:width="chartOptions.chart.width"
:height="chartOptions.chart.height"
:type="chartOptions.type"
:options="chartOptions"
:series="series"
/>
其中 key 是字符串类型的道具,我通过执行辅助函数从父级生成新密钥,
export function generateRandomString(value) {
let r = Math.random().toString(36).substring(7)
if (!value) return r
return `${value}_${r}`
}
*上面函数中的 value
参数是可选的。我传递图表名称是为了给键更多上下文。
如果有帮助请告诉我,我很想听听。
我在我的 Nuxt JS 项目中使用 Chart JS 和 Vue Chart JS 包装器。出于某种原因,尽管有新数据,但我的图表没有更新新数据。我的图表设置有一个名为 LineChart.vue
的组件,以及一个名为 LineChart.js
的插件,位于我的 plugins
目录中。
我的组件看起来像:
<template>
<div>
<line-chart :chart-data="customChartData" class="data-chart"></line-chart>
</div>
</template>
<style>
.data-chart canvas {
width: 100% !important;
height: auto !important;
}
</style>
<script>
import LineChart from '~/plugins/LineChart.js'
export default {
components: {
LineChart
},
props: {
chartKey: {
type: Number,
default: 0
},
groupBy: {
type: String,
default: 'hourly'
},
labels: {
type: Array,
default: null
},
datasets: {
type: Array,
default: null
},
options: {
type: Object,
default: () => ({})
}
},
data () {
return {
customChartData: {}
}
},
mounted () {
this.fillData()
},
methods: {
/*
** Fill data
*/
fillData () {
const labelsToUse = []
const labels = this.labels
const first = labels[0]
const last = labels[labels.length - 1]
let diff = 0
for (const [index, label] of labels.entries()) {
const periodStart = this.$dayjs(Date.parse(first))
const periodFinish = this.$dayjs(Date.parse(last))
diff = periodFinish.diff(periodStart, 'day', true)
if (!diff) {
labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format('MMM Do'))
}
labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format(`${diff > 1 ? 'MMM Do' : 'HH:mm'}`))
}
this.customChartData = {
labels: labelsToUse,
datasets: this.datasets,
options: this.options
}
}
}
}
</script>
我的插件看起来像...
import { Line, mixins } from 'vue-chartjs'
import _ from 'lodash';
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
data () {
return {
options: {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [{
gridLines: {
display: true,
color: '#eceaea'
},
}],
xAxes: [{
gridLines: {
display: false
},
ticks: {
autoSkip: true,
maxTicksLimit: window.innerWidth < 575 ? 2.1 : 4.1,
maxRotation: 0,
minRotation: 0
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 35
}
}
}
}
},
mounted () {
this.renderLineChart()
},
methods: {
/*
** Get chart options
*/
getChartOptions () {
return this.options
},
/*
** Render a line chart
*/
renderLineChart () {
const options = this.getChartOptions()
// this.chartdata is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.localData, options)
}
},
computed: {
localData: function() {
return this.chartData
}
},
watch: {
chartData: {
handler: function (val, oldVal) {
const options = this.getChartOptions()
const clone = _.cloneDeep(this.localData)
console.log(this.localData)
this._data._chart.update()
this.renderChart(clone, options)
},
deep: true
}
}
}
当我在我的插件的 watch 方法中记录 console.log(this.localData)
时,我没有看到我的 labels
更新了从 :labels="server[Object.keys(server)[0]].history.labels"
推送的新标签和数据在我调用折线图的网页内,我缺少什么?
调用我的图表组件的页面是:
<div class="col-span-12" v-for="(server, index) in servers" :key="index">
<div class="bg-white p-6 rounded-md">
<h3 class="text-md font-medium text-gray-900">{{ server[Object.keys(server)[0]].agent.agent }}</h3>
</div>
<hr v-if="server[Object.keys(server)[0]].history" />
<div v-if="server[Object.keys(server)[0]].history" class="bg-white p-6 rounded-md">
<h3 class="text-md font-medium text-gray-500 mb-3">Free memory</h3>
<div class="chart chart--generic">
<LineChart
:labels="server[Object.keys(server)[0]].history.labels"
:datasets="[{
fill: false,
borderWidth: 2.5,
pointBackgroundColor: '#fff',
borderColor: '#5046e5',
data: server[Object.keys(server)[0]].history.data,
}]"
/>
</div>
</div>
</div>
更新数组标签后,您可以尝试调用 fillData() 方法。
希望有用
我目前正在构建一个应用程序并使用 Nuxt 和 ApexCharts 并且遇到了非常相似的问题。我的数据正在更新,但我在图表中没有看到任何变化。我解决这个问题的方法是向我的图表组件添加一个 key
并手动强制它重新呈现。 Vue 使用 key
属性来跟踪已更改和未更改的内容。通过提供一个新的,我们强制重新渲染。
我的解决方案的一个例子是,
<apexcharts
v-if="chartOptions"
:id="chartId"
:key="key"
class="am2-utility-chart"
:class="[isCategoryType ? 'marginLeft' : '']"
:ref="chartId"
:width="chartOptions.chart.width"
:height="chartOptions.chart.height"
:type="chartOptions.type"
:options="chartOptions"
:series="series"
/>
其中 key 是字符串类型的道具,我通过执行辅助函数从父级生成新密钥,
export function generateRandomString(value) {
let r = Math.random().toString(36).substring(7)
if (!value) return r
return `${value}_${r}`
}
*上面函数中的 value
参数是可选的。我传递图表名称是为了给键更多上下文。
如果有帮助请告诉我,我很想听听。