VueJs + Chart.js - 避免 ref 进行反应性更新
VueJs + Chart.js - Avoid ref for reactive updates
我目前正在学习 VueJs 并摆弄 Chart.js (https://github.com/apertureless/vue-chartjs)。
我试图让甜甜圈具有反应性行为,但我只是使用 ref 属性 让它工作,据我所知,这是一种糟糕的风格。我的第一个问题是,避免 $refs 是好的风格的假设是否正确。
我的方法的第一个问题是我不知道 mixin,但是关于如何使用 vue-chartjs 的唯一示例反应性地使用了它(https://github.com/apertureless/vue-chartjs/blob/master/src/examples/ReactiveExample.js 是参考点)
我在我的 Vue 组件中创建了一个名为 updateData 的方法,它将重置我的组件 chartData,然后将其设置为道具数据。首先,这是我的代码:
chart.blade.php(网络视图):
<html>
<head>
<meta charset="utf-8">
<title>Testchart</title>
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<div id="app">
<h1>Testchart</h1>
<doughnut :data="doughnut_data" :options="doughnut_options" ref="chart"></doughnut>
<button-reduce v-on:numberreduced="reduce"></button-reduce>
</div>
<script src="js/app.js" charset="utf-8"></script>
</body>
</html>
app.js:
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('doughnut', require('./components/testDoughnut.vue'));
Vue.component('button-reduce', require('./components/button.vue'));
const app = new Vue({
el: '#app',
data: {
doughnut_data: {
labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
datasets: [
{
backgroundColor: [
'#41B883',
'#E46651',
'#00D8FF',
'#DD1B16'
],
data: [40, 20, 80, 10]
}
]
},
doughnut_options: {
responsive: true,
maintainAspectRatio: false
}
},
methods: {
reduce() {
this.doughnut_data.datasets[0].data[2] = this.doughnut_data.datasets[0].data[2] - 5;
this.$refs.chart.updateData();
}
}
});
最后但同样重要的是,我的 Vue 组件 testDoughnut.vue
<script>
import { Doughnut, mixins } from 'vue-chartjs'
export default Doughnut.extend({
mixins: [mixins.reactiveData],
props: ["data", "options"],
data() {
return {
chartData: ''
}
},
created() {
this.updateData();
},
mounted () {
this.renderChart(this.chartData, this.options)
},
methods: {
updateData() {
this.chartData = {}; // without this step, it does not work (no reactive behaviour). Why is this necessary?
this.chartData = this.data;
}
}
})
</script>
出现了以下问题:
- (从上面):避免 $refs 是一件好事吗?
- 为什么无法直接从我的网络视图更新图表数据?
:chartData="doughnut_data"
没有用,我需要使用自定义道具 'data'
- 在我的 testDoughnut.vue 中,必须先将 chartData 重置为空 JSON 对象,然后再将其分配给 this.data。为什么需要此重置?从桌面开发 (C#) 开始,我认为我可以只写
this.chartData = this.data
而不需要空对象。
- 有没有更好的方法来处理这个问题而不是我的方法(使用 ref)?
vue-chartjs作者在这里
关于混入:
包含两个mixin。 vue 中的 Mixins 只是将一些逻辑和功能提取到单独的文件中,因此您可以重用它们。
如docs中所述,有两个mixins。
- reactiveProp 和
- 反应数据
因为,主要有两种情况,即如何将数据传递给图表组件。例如,一种可能性是在 laravel 环境中,您可以通过 props 将数据直接传递给组件。
<my-chart :chart-data="..."></my-chart>
另一个用例是,如果您有一个 API 并发出一个获取 / API 请求。
但是那时你的图表数据不是prop,是vue的data()函数中的一个变量。
修复
好吧,你的代码有点过于复杂了。
你更需要 reactiveProp mixin。
<script>
import { Doughnut, mixins } from 'vue-chartjs'
export default Doughnut.extend({
mixins: [mixins.reactiveProp],
props: ["options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
</script>
mixin 将创建一个名为 chartData 的 prop 并向其添加一个 watcher。 每次数据更改时,它都会更新图表或 re-render。如果您添加新数据集,则需要 re-render 编辑图表。
您的问题
- 你不需要 $ref,如果你使用正确的 mixin
- 模板中的驼峰式需要用破折号'-'书写
- 可能有问题,因为您复制了数据属性。 mixin 总是自动将您的 chartData 创建为 属性 或 data() 函数变量。所以你不需要自己创建它。但是我想这可能是竞争条件。 vue的create()钩子里面没有设置数据的地方。 https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
我目前正在学习 VueJs 并摆弄 Chart.js (https://github.com/apertureless/vue-chartjs)。 我试图让甜甜圈具有反应性行为,但我只是使用 ref 属性 让它工作,据我所知,这是一种糟糕的风格。我的第一个问题是,避免 $refs 是好的风格的假设是否正确。
我的方法的第一个问题是我不知道 mixin,但是关于如何使用 vue-chartjs 的唯一示例反应性地使用了它(https://github.com/apertureless/vue-chartjs/blob/master/src/examples/ReactiveExample.js 是参考点) 我在我的 Vue 组件中创建了一个名为 updateData 的方法,它将重置我的组件 chartData,然后将其设置为道具数据。首先,这是我的代码:
chart.blade.php(网络视图):
<html>
<head>
<meta charset="utf-8">
<title>Testchart</title>
<link rel="stylesheet" href="css/app.css">
</head>
<body>
<div id="app">
<h1>Testchart</h1>
<doughnut :data="doughnut_data" :options="doughnut_options" ref="chart"></doughnut>
<button-reduce v-on:numberreduced="reduce"></button-reduce>
</div>
<script src="js/app.js" charset="utf-8"></script>
</body>
</html>
app.js:
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('doughnut', require('./components/testDoughnut.vue'));
Vue.component('button-reduce', require('./components/button.vue'));
const app = new Vue({
el: '#app',
data: {
doughnut_data: {
labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
datasets: [
{
backgroundColor: [
'#41B883',
'#E46651',
'#00D8FF',
'#DD1B16'
],
data: [40, 20, 80, 10]
}
]
},
doughnut_options: {
responsive: true,
maintainAspectRatio: false
}
},
methods: {
reduce() {
this.doughnut_data.datasets[0].data[2] = this.doughnut_data.datasets[0].data[2] - 5;
this.$refs.chart.updateData();
}
}
});
最后但同样重要的是,我的 Vue 组件 testDoughnut.vue
<script>
import { Doughnut, mixins } from 'vue-chartjs'
export default Doughnut.extend({
mixins: [mixins.reactiveData],
props: ["data", "options"],
data() {
return {
chartData: ''
}
},
created() {
this.updateData();
},
mounted () {
this.renderChart(this.chartData, this.options)
},
methods: {
updateData() {
this.chartData = {}; // without this step, it does not work (no reactive behaviour). Why is this necessary?
this.chartData = this.data;
}
}
})
</script>
出现了以下问题:
- (从上面):避免 $refs 是一件好事吗?
- 为什么无法直接从我的网络视图更新图表数据?
:chartData="doughnut_data"
没有用,我需要使用自定义道具 'data' - 在我的 testDoughnut.vue 中,必须先将 chartData 重置为空 JSON 对象,然后再将其分配给 this.data。为什么需要此重置?从桌面开发 (C#) 开始,我认为我可以只写
this.chartData = this.data
而不需要空对象。 - 有没有更好的方法来处理这个问题而不是我的方法(使用 ref)?
vue-chartjs作者在这里
关于混入: 包含两个mixin。 vue 中的 Mixins 只是将一些逻辑和功能提取到单独的文件中,因此您可以重用它们。
如docs中所述,有两个mixins。
- reactiveProp 和
- 反应数据
因为,主要有两种情况,即如何将数据传递给图表组件。例如,一种可能性是在 laravel 环境中,您可以通过 props 将数据直接传递给组件。
<my-chart :chart-data="..."></my-chart>
另一个用例是,如果您有一个 API 并发出一个获取 / API 请求。 但是那时你的图表数据不是prop,是vue的data()函数中的一个变量。
修复
好吧,你的代码有点过于复杂了。
你更需要 reactiveProp mixin。
<script>
import { Doughnut, mixins } from 'vue-chartjs'
export default Doughnut.extend({
mixins: [mixins.reactiveProp],
props: ["options"],
mounted () {
this.renderChart(this.chartData, this.options)
}
})
</script>
mixin 将创建一个名为 chartData 的 prop 并向其添加一个 watcher。 每次数据更改时,它都会更新图表或 re-render。如果您添加新数据集,则需要 re-render 编辑图表。
您的问题
- 你不需要 $ref,如果你使用正确的 mixin
- 模板中的驼峰式需要用破折号'-'书写
- 可能有问题,因为您复制了数据属性。 mixin 总是自动将您的 chartData 创建为 属性 或 data() 函数变量。所以你不需要自己创建它。但是我想这可能是竞争条件。 vue的create()钩子里面没有设置数据的地方。 https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram