在 nuxt.js 项目中重新渲染 vue-chart
Rerender vue-chart in a nuxt.js project
我正在做一个nuxt项目,需要画一些图表。为此,我使用 vue-chartjs 作为插件。不幸的是,图表数据是在图表绘制后获取的,这导致图表为空。当数据准备好时,我找不到访问插件和重新呈现图表的方法。这是插件的代码:
// plugins/vue-chart.js
import Vue from 'vue'
import { Bar, Doughnut, Line, Pie } from 'vue-chartjs'
const registerComponent = function (name, originalComponent) {
Vue.component(
name,
{
extends: originalComponent,
props: ['data', 'options'],
mounted () {
this.renderChart(this.data, this.options)
},
updated () {
this.renderChart(this.data, this.options)
}
}
)
}
registerComponent('BarChart', Bar)
registerComponent('DoughnutChart', Doughnut)
registerComponent('LineChart', Line)
registerComponent('PieChart', Pie)
下面是我如何使用插件绘制折线图:
components/Charts.vue
<template>
<client-only>
<LineChart :data="lineData" :options="options" />
</client-only>
</template>
<script>
export default {
data() {
return {
loading: true,
lineData: {
labels: [],
datasets: [
{
label: 'Close',
data: [],
},
{
label: 'High',
data: [],
},
],
},
options: {
responsive: true,
scales: {
x: {
display: true,
title: {
display: true,
},
},
y: {
display: true,
title: {
display: true,
text: 'Value',
},
},
},
},
}
},
async mounted() {
try {
const response = await this.$axios.get('/api/entries')
if (response.status === 200) {
for (let i = 0; i < response.data.length; i++) {
this.lineData.labels.push(response.data[i].date)
this.lineData.datasets[0].data.push(response.data[i].close)
this.lineData.datasets[1].data.push(response.data[i].high)
}
}
} catch (e) {
console.log(e)
}
},
}
</script>
我很高兴收到有关如何解决此问题的任何建议!
编辑
我不得不降级 chart.js
和 vue-chartjs
的版本,以便项目编译。
这是我的package.json
{
"name": "xyz",
"version": "1.0.0",
"private": true,
"scripts": {
"dev-fe": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint": "npm run lint:js"
},
"dependencies":
"@nuxtjs/axios": "^5.13.6",
"chart.js": "^2.7.1",
"core-js": "^3.15.1",
"nuxt": "^2.15.7",
"vue": "^2.6.14",
"vue-chartjs": "^3.4.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.14.7",
"@nuxtjs/eslint-config": "^6.0.1",
"@nuxtjs/eslint-module": "^3.0.2",
"@nuxtjs/tailwindcss": "^4.2.0",
"eslint": "^7.29.0",
"eslint-plugin-nuxt": "^2.0.0",
"eslint-plugin-vue": "^7.12.1",
"postcss": "^8.3.5"
}
}
我在 nuxt.config.js
中几乎使用默认值,除了我添加了
{ src: '~/plugins/vue-chart.js', mode: 'client' }
到插件。
好的,我得到了一个工作示例,如下所示。
这是我的 vue-chartjs.js
插件
import Vue from 'vue'
import { Bar, Doughnut, Line, Pie, mixins } from 'vue-chartjs'
const registerComponent = function (name, originalComponent) {
Vue.component(name, {
extends: originalComponent,
mixins: [mixins.reactiveProp],
props: {
chartData: {
type: Object,
default: () => {},
},
chartOptions: {
type: Object,
default: () => {},
},
},
mounted() {
this.renderChart(this.chartData, this.chartOptions)
},
})
}
registerComponent('BarChart', Bar)
registerComponent('DoughnutChart', Doughnut)
registerComponent('LineChart', Line)
registerComponent('PieChart', Pie)
/pages/index.vue
<template>
<div>
<line-chart
:key="updated"
:chart-data="lineData"
:chart-options="options"
/>
</div>
</template>
<script>
import FakeData from '@/fake.json'
export default {
data() {
return {
updated: 0,
lineData: {
labels: [],
datasets: [
{
label: 'Data One',
backgroundColor: '',
data: [],
},
{
label: 'Data Two',
backgroundColor: '',
data: [],
},
],
},
options: {
responsive: true,
scales: {
x: {
display: true,
title: {
display: true,
},
},
y: {
display: true,
title: {
display: true,
text: 'Value',
},
},
},
},
}
},
async fetch() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
const data = await response.json()
console.log('fake API title fetched:', data.title)
const actualData = FakeData.data
for (let i = 0; i < actualData.length; i++) {
this.lineData.labels.push(actualData[i].date)
this.lineData.datasets[0].backgroundColor = actualData[i].color1
this.lineData.datasets[0].data.push(actualData[i].close)
this.lineData.datasets[1].backgroundColor = actualData[i].color2
this.lineData.datasets[1].data.push(actualData[i].high)
}
this.updated++
},
}
</script>
和我的假 .json
API 数据,因为我没有 API 来获取一些真实数据
{
"data": [
{
"date": "Jan",
"color1": "#EC368D",
"color2": "#51E5FF",
"close": "0.4",
"high": "0.7"
},
{
"date": "Feb",
"color1": "#EC368D",
"color2": "#51E5FF",
"close": "0.2",
"high": "0.5"
},
{
"date": "Mar",
"color1": "#EC368D",
"color2": "#51E5FF",
"close": "0.6",
"high": "0.8"
}
]
}
我仍然嘲笑了一个 API 调用,所以它应该可以很好地作为您的示例。
这背后的想法是使用 key
hack,这并不是那么好,但是嗯,维护者并没有真正帮助人们正确地使用 IMO。
所以这仍然是最好的。
这是我的最终结果和相关的Github repo。
我正在做一个nuxt项目,需要画一些图表。为此,我使用 vue-chartjs 作为插件。不幸的是,图表数据是在图表绘制后获取的,这导致图表为空。当数据准备好时,我找不到访问插件和重新呈现图表的方法。这是插件的代码:
// plugins/vue-chart.js
import Vue from 'vue'
import { Bar, Doughnut, Line, Pie } from 'vue-chartjs'
const registerComponent = function (name, originalComponent) {
Vue.component(
name,
{
extends: originalComponent,
props: ['data', 'options'],
mounted () {
this.renderChart(this.data, this.options)
},
updated () {
this.renderChart(this.data, this.options)
}
}
)
}
registerComponent('BarChart', Bar)
registerComponent('DoughnutChart', Doughnut)
registerComponent('LineChart', Line)
registerComponent('PieChart', Pie)
下面是我如何使用插件绘制折线图:
components/Charts.vue
<template>
<client-only>
<LineChart :data="lineData" :options="options" />
</client-only>
</template>
<script>
export default {
data() {
return {
loading: true,
lineData: {
labels: [],
datasets: [
{
label: 'Close',
data: [],
},
{
label: 'High',
data: [],
},
],
},
options: {
responsive: true,
scales: {
x: {
display: true,
title: {
display: true,
},
},
y: {
display: true,
title: {
display: true,
text: 'Value',
},
},
},
},
}
},
async mounted() {
try {
const response = await this.$axios.get('/api/entries')
if (response.status === 200) {
for (let i = 0; i < response.data.length; i++) {
this.lineData.labels.push(response.data[i].date)
this.lineData.datasets[0].data.push(response.data[i].close)
this.lineData.datasets[1].data.push(response.data[i].high)
}
}
} catch (e) {
console.log(e)
}
},
}
</script>
我很高兴收到有关如何解决此问题的任何建议!
编辑
我不得不降级 chart.js
和 vue-chartjs
的版本,以便项目编译。
这是我的package.json
{
"name": "xyz",
"version": "1.0.0",
"private": true,
"scripts": {
"dev-fe": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint": "npm run lint:js"
},
"dependencies":
"@nuxtjs/axios": "^5.13.6",
"chart.js": "^2.7.1",
"core-js": "^3.15.1",
"nuxt": "^2.15.7",
"vue": "^2.6.14",
"vue-chartjs": "^3.4.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.14.7",
"@nuxtjs/eslint-config": "^6.0.1",
"@nuxtjs/eslint-module": "^3.0.2",
"@nuxtjs/tailwindcss": "^4.2.0",
"eslint": "^7.29.0",
"eslint-plugin-nuxt": "^2.0.0",
"eslint-plugin-vue": "^7.12.1",
"postcss": "^8.3.5"
}
}
我在 nuxt.config.js
中几乎使用默认值,除了我添加了
{ src: '~/plugins/vue-chart.js', mode: 'client' }
到插件。
好的,我得到了一个工作示例,如下所示。
这是我的 vue-chartjs.js
插件
import Vue from 'vue'
import { Bar, Doughnut, Line, Pie, mixins } from 'vue-chartjs'
const registerComponent = function (name, originalComponent) {
Vue.component(name, {
extends: originalComponent,
mixins: [mixins.reactiveProp],
props: {
chartData: {
type: Object,
default: () => {},
},
chartOptions: {
type: Object,
default: () => {},
},
},
mounted() {
this.renderChart(this.chartData, this.chartOptions)
},
})
}
registerComponent('BarChart', Bar)
registerComponent('DoughnutChart', Doughnut)
registerComponent('LineChart', Line)
registerComponent('PieChart', Pie)
/pages/index.vue
<template>
<div>
<line-chart
:key="updated"
:chart-data="lineData"
:chart-options="options"
/>
</div>
</template>
<script>
import FakeData from '@/fake.json'
export default {
data() {
return {
updated: 0,
lineData: {
labels: [],
datasets: [
{
label: 'Data One',
backgroundColor: '',
data: [],
},
{
label: 'Data Two',
backgroundColor: '',
data: [],
},
],
},
options: {
responsive: true,
scales: {
x: {
display: true,
title: {
display: true,
},
},
y: {
display: true,
title: {
display: true,
text: 'Value',
},
},
},
},
}
},
async fetch() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
const data = await response.json()
console.log('fake API title fetched:', data.title)
const actualData = FakeData.data
for (let i = 0; i < actualData.length; i++) {
this.lineData.labels.push(actualData[i].date)
this.lineData.datasets[0].backgroundColor = actualData[i].color1
this.lineData.datasets[0].data.push(actualData[i].close)
this.lineData.datasets[1].backgroundColor = actualData[i].color2
this.lineData.datasets[1].data.push(actualData[i].high)
}
this.updated++
},
}
</script>
和我的假 .json
API 数据,因为我没有 API 来获取一些真实数据
{
"data": [
{
"date": "Jan",
"color1": "#EC368D",
"color2": "#51E5FF",
"close": "0.4",
"high": "0.7"
},
{
"date": "Feb",
"color1": "#EC368D",
"color2": "#51E5FF",
"close": "0.2",
"high": "0.5"
},
{
"date": "Mar",
"color1": "#EC368D",
"color2": "#51E5FF",
"close": "0.6",
"high": "0.8"
}
]
}
我仍然嘲笑了一个 API 调用,所以它应该可以很好地作为您的示例。
这背后的想法是使用 key
hack,这并不是那么好,但是嗯,维护者并没有真正帮助人们正确地使用 IMO。
所以这仍然是最好的。
这是我的最终结果和相关的Github repo。