开发者问题收集

Chart.js-未捕获的 TypeError:在多个图表的非对象上调用 Object.defineProperty

2019-01-11
6115

我想用相同的类名渲染多个图表。具有相同类名的 div 包含 canvas 对象。大多数选项相同,但有几个不同。我想通过 data 属性发送它们。一切都正常,但是当我要在 dom 对象上选择 canvas 元素时,它会出现:

Uncaught TypeError: Object.defineProperty called on non-object

我不知道为什么会这样。

以下是 html 代码

<td
    class ="crypt-marketcap-canvas"
    data-charts ="[65,59,81,81,56,55,40,80,90]" 
    data-bg = "d3f0df"
    data-border = "8cd8aa">
    <canvas />
</td>

和 js 代码是

var charts = document.getElementsByClassName("crypt-marketcap-canvas");

for( let chart of charts ){
  let data = chart.dataset.charts;
  // console.log(chart.dataset.charts);
  let bg = chart.dataset.bg;
  let border = chart.dataset.border;

  let canvas = chart.querySelector('canvas');
  // console.log(canvas);
  let ctx = canvas.getContext('2d');
  console.log(ctx);
  let lineChartData = {
    labels : ["1","2","3","4","5","6","7","8","9"],
    datasets : [
        {
            backgroundColor : '#' + bg,
            borderColor : '#' + border,
            data : data,
            bezierCurve : true
        }
    ]  
  }
  new Chart(ctx, { //Error is showing on this line
    type:"line",
    data:lineChartData,
    options:options
  });
}
1个回答

此处的问题是 data 是一个字符串 “[65,59,81,81,56,55,40,80,90]” ,而 Chart 无法理解该字符串。

如果您执行 JSON.parse ,它将起作用:

let data = JSON.parse(chart.dataset.charts);

这会将数据转换回数组,我猜,这是您的意图。

var charts = document.getElementsByClassName("crypt-marketcap-canvas");

for( let chart of charts ){
  let data = JSON.parse(chart.dataset.charts);
  // console.log(chart.dataset.charts);
  let bg = chart.dataset.bg;
  let border = chart.dataset.border;

  let canvas = chart.querySelector('canvas');
  let ctx = canvas.getContext('2d');
  let lineChartData = {
    labels : ["1","2","3","4","5","6","7","8","9"],
    datasets : [
        {
            backgroundColor : '#' + bg,
            borderColor : '#' + border,
            data : data,
            bezierCurve : true
        }
    ]  
  }
  new Chart(ctx, { //Error is showing on this line
    type:"line",
    data:lineChartData,
    options: {}
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>

<table>
  <tbody>
    <tr>
      <td
    class ="crypt-marketcap-canvas"
    data-charts ="[65,59,81,81,56,55,40,80,90]" 
    data-bg = "d3f0df"
    data-border = "8cd8aa">
    <canvas />
</td>
    </tr>
  </tbody>
  </table>

额外

如果您可以控制如何将 data-charts 写入 DOM,我会说避免使用 [ ,而只需执行如下操作:

<td
    class ="crypt-marketcap-canvas"
    data-charts ="65,59,81,81,56,55,40,80,90" 
    data-bg = "d3f0df"
    data-border = "8cd8aa">
    <canvas />
</td>

然后在您的脚本上: let data = chart.dataset.charts.split(','); 导致相同的结果。

我推荐这样做的原因是,如果发生奇怪的事情, JSON.parse 可能会引发异常,因此您必须将其包装在 try/catch 块中。

Antonio Laguna
2019-01-11