jackieli123723 / jackieli123723.github.io

✅lilidong 个人博客
9 stars 0 forks source link

vue+chart.js封装踩坑 #39

Open jackieli123723 opened 6 years ago

jackieli123723 commented 6 years ago

vue+chart.js万能封装

线上效果用chrome打开更好没做移动端适配

仓库地址

喜欢的可以给我个点亮

例如我有一个demo.vue去渲染

<template>
       <div class="chart-container commits-per-quarter">
            <canvas id="quarterCommitCount"></canvas>
        </div>

</template>

<script>
import Chart from 'chart.js'
export default {
    data () {
      return {
          chart: null,
          dataLine: {
            labels: ["2016-Q3", "2016-Q4", "2017-Q1", "2017-Q2", "2017-Q3", "2017-Q4"],
            datasets: [{
                label: "Commits",
                data: [12,35,18,69,147,52],
                backgroundColor: "rgba(67, 142, 233, 0.2)",
                borderColor: "rgba(67, 142, 233, 1)",
                lineTension: 0
            }]
        },
        optionsLine: {
            maintainAspectRatio: false,
            animation: false,
            scales: {
                xAxes: [{
                    display: false
                }],
                yAxes: [{
                    position: "right"
                }]
            },
            legend: {
                display: false
            },
            tooltips: {
                intersect: false
            }
        }
      }
    },
    methods: {  
      getCharts () {
        this.$gitHubApi.getChart(this).then(response => {
          if (response.data) {
            this.chart = response.data

          }
        })
      }
    },
    created(){
        this.getCharts()
    },
    mounted () {
      this.$nextTick(() => {
            function lineChart(objectName, data) {
                new Chart(document.getElementById(objectName).getContext("2d"), {
                    type: "line",
                    data: {
                        labels: Object.keys(data[objectName]),
                        datasets: [{
                            label: "Commits",
                            data: Object.values(data[objectName]),
                            backgroundColor: "rgba(67, 142, 233, 0.2)",
                            borderColor: "rgba(67, 142, 233, 1)",
                            lineTension: 0
                        }]
                    },
                    options: {
                        maintainAspectRatio: false,
                        animation: false,
                        scales: {
                            xAxes: [{
                                display: false
                            }],
                            yAxes: [{
                                position: "right"
                            }]
                        },
                        legend: {
                            display: false
                        },
                        tooltips: {
                            intersect: false
                        }
                    }
                });
            }
             lineChart("quarterCommitCount", chart);

      })
    }
  }
</script>

控制台报错

mounted 钩子中的chart 对象找不到 not defined 或者chart 数据没定义
这里务必要把chart 设置为null 或者 {} 不能为空

既然一个页面有好几个图标 是不是我可以个封装个组件

//成品伸手党可拿去

<template>
  <canvas class="chartjs" :width="width" :height="height"></canvas>
</template>

<script>
import Chart from 'chart.js' // With moment.js
const types = ['line', 'bar', 'radar', 'polarArea', 'pie', 'doughnut', 'bubble', 'scatter']
export default {
  props: {
    width: Number,
    height: Number,
    type: {
      type: String,
      required: true,
      validator: val => types.includes(val)
    },
    data: {
      type: Object,
      required: true,
      default: () => ({})
    },
    options: {
      type: Object,
      default: () => ({})
    },
    plugins: {
      type: [Object, Array],
      default: () => ({})
    }
  },
  mounted () {
    this.resetChart()
  },
  data () {
    return {
      chart: null
    }
  },
  methods: {
    resetChart () {
      if (this.chart)
        this.chart.destroy()
      this.chart = new Chart(this.$el, {
        type: this.type,
        data: this.data,
        options: this.options,
        plugins: this.plugins
      })
    }
  },
  watch: {
    type () {
      this.$nextTick(() => this.resetChart())
    },
    data () {
      this.chart.update()
    },
    options () {
      this.$nextTick(() => this.resetChart())
    }
  }
}
</script>

<style lang="scss">
  canvas.chartjs {
    max-width: 100%;
  }
</style>

封装的过程要解决的问题

核心

  mounted () {
    this.resetChart()
  },
  data () {
    return {
      chart: null
    }
  },
  methods: {
    resetChart () {
     //如果存在先创建一个chart 对象 必须给 new Chart 赋值一个
     //改变时候要先销毁上一次的chart对象

      if (this.chart)
        this.chart.destroy()
      this.chart = new Chart(this.$el, {
        type: this.type,
        data: this.data,
        options: this.options,
        plugins: this.plugins
      })
    }
  },
  watch: {
    type () {
      //监听chart类型dom准备好后用resetChart 初始化
      this.$nextTick(() => this.resetChart())
    },
    data () {
      //数据更新要跟新chart update
      //官网找到
      //.update( )
Calling update() on your Chart instance will re-render the chart with anyupdated values, allowing you to edit the value of multiple existing points,then render those in one animated render loop.

      this.chart.update()
    },
    options () {
    //监听chart配置dom准备好后用resetChart 初始化
      this.$nextTick(() => this.resetChart())
    }
  }

用法

<template>

    <div class="chart-container commits-per-quarter">
         <charts :type="'line'" :data="dataLine" :options="optionsLine" ></charts>
    </div>

</template>

<script>
import Chart from 'chart.js'
import Charts from './ChartPie.vue'

  export default {
    data () {
      return {
          dataLine: {
            labels: ["2016-Q3", "2016-Q4", "2017-Q1", "2017-Q2", "2017-Q3", "2017-Q4"],
            datasets: [{
                label: "Commits",
                data: [12,35,18,69,147,52],
                backgroundColor: "rgba(67, 142, 233, 0.2)",
                borderColor: "rgba(67, 142, 233, 1)",
                lineTension: 0
            }]
        },
        optionsLine: {
            maintainAspectRatio: false,
            animation: false,
            scales: {
                xAxes: [{
                    display: false
                }],
                yAxes: [{
                    position: "right"
                }]
            },
            legend: {
                display: false
            },
            tooltips: {
                intersect: false
            }
        }
      }
    },
    components: {
    Charts
    },
    computed: {

    }
  }
</script>