使用`chartjs-plugin-trendline`时,与`vue-chartjs v4`一起使用会出现响应性问题。

huangapple go评论58阅读模式
英文:

Reactivity issue when using vue-chartjs v4 with `chartjs-plugin-trendline`

问题

以下是代码部分的翻译:

<template>
  <div>
    <line-chart
      ref="chart"
      :chartData="chartData"
      :chartOptions="chartOptions"
    />
    <button @click="toggleTrendline">
      {{ showTrendline ? "隐藏" : "显示" }} 趋势线
    </button>
  </div>
</template>

<script>
import { Line } from "vue-chartjs/legacy";

export default {
  components: { "line-chart": Line },
  data() {
    return {
      showTrendline: false,
    };
  },
  computed: {
    chartOptions() {
      return {
        responsive: true,
        maintainAspectRatio: false,
      };
    },
    chartData() {
      let data = {
        labels: [
          "一月",
          "二月",
          "三月",
          "四月",
          "五月",
          "六月",
          "七月",
          "八月",
          "九月",
          "十月",
          "十一月",
          "十二月",
        ],
        datasets: [
          {
            label: "数据一",
            backgroundColor: "#f87979",
            data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11],
          },
        ],
      };
      if (this.showTrendline)
        data.datasets[0].trendlineLinear = {
          colorMin: "#2d9cdb",
          colorMax: "#2d9cdb",
          lineStyle: "solid",
          width: 2,
        };
      else delete data.datasets[0].trendlineLinear;
      return data;
    },
  },
  methods: {
    toggleTrendline() {
      this.showTrendline = !this.showTrendline;
      if (!this.showTrendline) {
        this.$refs.chart.getCurrentChart().update("none");
      }
    },
  },
};
</script>

请注意,代码中的按钮文本和标签已从英文翻译为中文。

英文:

I have a linear line chart and a button to toggle the visibility of the trendline.
Showing the trendline works fine, but when I click the button again to hide the trendline, nothing happens.
I have no idea why, perhaps it's a bug in vue-chartjs v4.2.1 or maybe I'm doing something wrong with my code. I even try to manually update the chart via ref, but no luck.

&lt;template&gt;
&lt;div&gt;
&lt;line-chart
ref=&quot;chart&quot;
:chartData=&quot;chartData&quot;
:chartOptions=&quot;chartOptions&quot;
/&gt;
&lt;button @click=&quot;toggleTrendline&quot;&gt;
{{ showTrendline ? &quot;Hide&quot; : &quot;Show&quot; }} trendline
&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
import { Line } from &quot;vue-chartjs/legacy&quot;;
export default {
components: { &quot;line-chart&quot;: Line },
data() {
return {
showTrendline: false,
};
},
computed: {
chartOptions() {
return {
responsive: true,
maintainAspectRatio: false,
};
},
chartData() {
let data = {
labels: [
&quot;January&quot;,
&quot;February&quot;,
&quot;March&quot;,
&quot;April&quot;,
&quot;May&quot;,
&quot;June&quot;,
&quot;July&quot;,
&quot;August&quot;,
&quot;September&quot;,
&quot;October&quot;,
&quot;November&quot;,
&quot;December&quot;,
],
datasets: [
{
label: &quot;Data One&quot;,
backgroundColor: &quot;#f87979&quot;,
data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11],
},
],
};
if (this.showTrendline)
data.datasets[0].trendlineLinear = {
colorMin: &quot;#2d9cdb&quot;,
colorMax: &quot;#2d9cdb&quot;,
lineStyle: &quot;solid&quot;,
width: 2,
};
else delete data.datasets[0].trendlineLinear;
return data;
},
},
methods: {
toggleTrendline() {
this.showTrendline = !this.showTrendline;
if (!this.showTrendline) {
this.$refs.chart.getCurrentChart().update(&quot;none&quot;);
}
},
},
};
&lt;/script&gt;

Here is a reproducible sandbox: https://codesandbox.io/s/vue-chartjs-demo-forked-kujr7m?file=/src/components/LineChart.vue:0-1463

Here is a working version with vanilla js: https://codesandbox.io/s/working-trendline-q31h0o?file=/src/index.js
It works fine with vanilla js, so I believe either my vue code is wrong or vue-chartjs has a bug.

答案1

得分: 1

I'll provide the translation of the code section as requested:

<template>
  <div>
    <line-chart ref="chart" :chartData="data" :chartOptions="chartOptions" />
    <button @click="toggleTrendline">
      {{ showTrendline ? "隐藏" : "显示" }} 趋势线
    </button>
  </div>
</template>

<script>
import { Line } from "vue-chartjs/legacy";

export default {
  components: { "line-chart": Line },
  data() {
    const dataset = {
      label: "数据一",
      backgroundColor: "#f87979",
      data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11],
    };

    return {
      showTrendline: false,
      dataset: dataset,
      data: {
        labels: [
          "一月",
          "二月",
          "三月",
          "四月",
          "五月",
          "六月",
          "七月",
          "八月",
          "九月",
          "十月",
          "十一月",
          "十二月",
        ],
        datasets: [dataset],
      },
    };
  },
  computed: {
    chartOptions() {
      return {
        responsive: true,
        maintainAspectRatio: false,
      };
    },
  },
  methods: {
    toggleTrendline() {
      this.showTrendline = !this.showTrendline;
      if (this.showTrendline) {
        this.$refs.chart.$data._chart.data.datasets[0].trendlineLinear = {
          colorMin: "#2d9cdb",
          colorMax: "#2d9cdb",
          lineStyle: "solid",
          width: 2,
        };
      } else {
        delete this.$refs.chart.$data._chart.data.datasets[0].trendlineLinear;
      }

      console.log(this.$refs.chart.$data._chart);

      this.$refs.chart.$data._chart.update();
    },
  },
};
</script>

This is the translated code section.

英文:

Didnt test this on runtime, but maybe the logic should work like this

&lt;template&gt;
&lt;div&gt;
&lt;line-chart ref=&quot;chart&quot; :chartData=&quot;data&quot; :chartOptions=&quot;chartOptions&quot; /&gt;
&lt;button @click=&quot;toggleTrendline&quot;&gt;
{{ showTrendline ? &quot;Hide&quot; : &quot;Show&quot; }} trendline
&lt;/button&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
import { Line } from &quot;vue-chartjs/legacy&quot;;
export default {
components: { &quot;line-chart&quot;: Line },
data() {
const dataset = {
label: &quot;Data One&quot;,
backgroundColor: &quot;#f87979&quot;,
data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11],
};
return {
showTrendline: false,
dataset: dataset,
data: {
labels: [
&quot;January&quot;,
&quot;February&quot;,
&quot;March&quot;,
&quot;April&quot;,
&quot;May&quot;,
&quot;June&quot;,
&quot;July&quot;,
&quot;August&quot;,
&quot;September&quot;,
&quot;October&quot;,
&quot;November&quot;,
&quot;December&quot;,
],
datasets: [dataset],
},
};
},
computed: {
chartOptions() {
return {
responsive: true,
maintainAspectRatio: false,
};
},
},
methods: {
toggleTrendline() {
this.showTrendline = !this.showTrendline;
if (this.showTrendline) {
this.$refs.chart.$data._chart.data.datasets[0].trendlineLinear = {
colorMin: &quot;#2d9cdb&quot;,
colorMax: &quot;#2d9cdb&quot;,
lineStyle: &quot;solid&quot;,
width: 2,
};
} else {
delete this.$refs.chart.$data._chart.data.datasets[0].trendlineLinear;
}
console.log(this.$refs.chart.$data._chart);
this.$refs.chart.$data._chart.update();
},
},
};
&lt;/script&gt;

答案2

得分: 1

似乎Vue的响应性运作正常,这可能是"chartjs-plugin-trendline"插件的一个bug。我们可以证明响应性确实有效,因为当我们更改trendlineLinear属性的值时,图表也会正常变化。在我看来,可能是图表(也许在这个版本中)无法在创建后删除trendlineLinear,但我对此不太确定。我能想到的唯一简单解决方法是,而不是删除trendLineLinear属性,当我们想隐藏它时,将趋势线的颜色更改为transparent

这是一个可运行的代码示例

英文:

It seems like the vue reactivity works just fine, it's probably a bug on the &quot;chartjs-plugin-trendline&quot; plugin. We can prove that the reactivity actually works, because when we change the value of the trendlineLinear property, the chart changes just fine. The way I see it, it's probably that the chart (maybe on this version) simply can't remove the trendlineLinear once it's created, but i'm not really sure about that. The only easy workaround I could think of is, instead of deleting the trendLineLinear property, we change the color of the trendline to transparent when we want to hide it.

      ...
if (this.showTrendline)
data.datasets[0].trendlineLinear = {
colorMin: &quot;#2d9cdb&quot;,
colorMax: &quot;#2d9cdb&quot;,
lineStyle: &quot;solid&quot;,
width: 2,
};
else
data.datasets[0].trendlineLinear = {
colorMin: &quot;rgba(0,0,0, 0)&quot;,
colorMax: &quot;rgba(0,0,0, 0)&quot;,
lineStyle: &quot;solid&quot;,
width: 2,
};
...

Here is the working forked code sandbox.

答案3

得分: 0

...
else
data.datasets[0].trendlineLinear = null;

查看此代码沙盒

英文:
...
else
data.datasets[0].trendlineLinear = null;

See this code sand box

huangapple
  • 本文由 发表于 2023年2月23日 19:55:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75544497.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定