2019-07-29 vue2.0 自定义 柱状图 (Echarts)组件

子组件

<!-- 自定义 echart 组件 -->
<template>
  <div>
    <!-- echart表格 -->
    <div :id="myChartId" :style="echartStyle"></div>
    <Spin size="large" fix v-if="isLoadding"></Spin>
  </div>
</template>
 
<script>
import echarts from "echarts";
export default {
  props: {
    // ID
    myChartId: {
      type: String,
      default: "myChartBarId"
    }, 
    // 样式
    echartStyle: {
      type: String,
      default: ""
    }, 
    // 标题文本
    titleText: {
      type: String,
      default: ""
    },
     // 标题文本
    subText: {
      type: String,
      default: ""
    },
    //是否包含坐标轴的刻度标签
    containLabel: {
      type: Boolean,
      default: false
    },
    // 条形图数据
    opinionData: {
      type: Object,
      default() {
        return {};
      }
    },
    //条形图颜色
    barColor: {
      type: String,
      default: ""
    },
  },
  data() {
    return {
      isLoadding:true
    };
  },
  watch: {
    opinionData(val, oldval) {
      this.$nextTick(function() {
        this.isLoadding=false;
        this.drawPie(this.myChartId);
      });
    }
  },
  methods: {
    // 监听扇形图点击
    eConsole(param) {
      // 向父组件传值
      this.$emit("echarEvent", param);
    }, // 绘制饼状图
    drawPie(id) {
      this.charts = echarts.init(document.getElementById(id));
      this.charts.on("click", this.eConsole);
      this.charts.setOption({
        title: {
          text: this.titleText, // 标题文本
          subtext: this.subText, //副标题文本
          x: '55%',//文字距离左边大小
          textAlign: 'center'
        },
        tooltip: {
            // trigger: 'item',
            // formatter: "{a} <br/>{b}: {c} ({d}%)"//模板变量有 {a}、{b}、{c}、{d},分别表示系列名,数据名,数据值,百分比。
        },
        grid: [{
            top: 50,//组件离容器上侧的距离。
            left: 10,//组件离容器左侧的距离。
            containLabel: this.containLabel//是否包含坐标轴的刻度标签。
        }],
        xAxis: [{
            type: 'value',//数值轴类型
            splitLine: {//是否显示轴线
                show: false
            }
        }],
        yAxis: [{
            type: 'category',
            data: Object.keys(this.opinionData),//条形图y轴标签数据
            axisLabel: {
                interval: 0,//坐标轴刻度标签的显示间隔,设置成 0 强制显示所有标签
                rotate: 30//y轴标签旋转角度
            },
            splitLine: {//是否显示轴线
                show: false
            }
        }],
        series: [
            {
                type: 'bar',//数据条
                stack: 'chart',//堆叠
                z: 3,
                label: {
                    normal: {
                        position: 'right',
                        show: true,
                    }
                },
                itemStyle: {
                    normal: {
                        color: this.barColor
                    }
                },
                data: this.changeOpinionData(this.opinionData)
            },
            {
                type: 'bar',//背景条
                stack: 'chart',//堆叠
                silent: true,
                itemStyle: {
                    normal: {
                        color: '#EEEEEE'
                    }
                },
                data: this.getRest(this.opinionData)
            }
        ],
      });
    },
    changeOpinionData(ary){//取条形数据值
        var newAry=Object.keys(ary).map(function (key) {
            return ary[key];
        })
        return newAry;
    },
    getTotol(ary){//统计总数
        var totol=Object.keys(ary).reduce(function (all, key) {
            return all + ary[key];
        }, 0)
        return totol;
    },
    getRest(ary){//统计余量
        var that=this;
        var rest=Object.keys(ary).map(function (key) {
            return that.getTotol(ary) - ary[key];
        })
        return rest;
    }
  }
};
</script>

父组件引用示例

<style lang="less">
@import "./home.less";
@import "../../styles/common.less";
</style>
<template>
    <Row>
        <Col span="8">
            <draw-bar
              :myChartId="'mychart4'"
              :echartStyle="'width:450px;height:300px;margin:auto'"
              :titleText="drawPieInfo.titleText"
              :subText="drawPieInfo.subText"
              :containLabel="drawPieInfo.containLabel"
              :barColor="drawPieInfo.barColor"
              :opinionData="drawPieInfo.opinionData"
              @echarEvent="echarEvent($event,'案由统计')"
        ></draw-bar>
        </Col>
    </Row>
</template>

<script>
import drawBar from "@/components/zhEchart/drawBar.vue";
import {
   countLawCase
} from '@/api/homeDate';

export default {
    name: 'home',
    components: {
        drawBar
    },
    data () {
        return {
            drawPieInfo: {
                titleText: "案由统计",
                subText: "总计",
                containLabel: true,
                barColor: "#3FB1E3",
                opinionData: {} //条形数据
            },
            lawCaseCount:[],//案件状态
        };
    },
    mounted () {
      this.initChart();
    },
    methods: {
        initChart(){//初始化chart数据
            countLawCase().then(res=>{
               if(res.data.state==100){
                    let data=res.data.data;
                    this.lawCaseCount=data.lawCaseCount;
                    var that=this;
                    var ary=Object.keys(this.lawCaseCount).map(function (key) {
                        return {
                            name: key,
                            value: that.lawCaseCount[key]//获取条形数据
                        }
                    });
                    this.drawPieInfo.opinionData=ary;//设置条形数据
                    this.drawPieInfo.subText = "总计:" + this.getTotol(this.lawCaseCount); //设置总数
               }else{
                   this.$Message.error(res.data.message);
               }
            });
       },
       echarEvent(){

       },
       getTotol(ary) {
         //统计总数
         var totol = Object.keys(ary).reduce(function(all, key) {
           return all + ary[key];
         }, 0);
         return totol;
       },
    },
};
</script>

值得注意的是:由于echart数据依赖DOM更新,再次赋值时需要重新初始化echart,在父组件异步获取数据传入子组件时,要用watch监听传入的值并重新进行DOM渲染,数据更新了但视图并没有及时更新因此就需要$nextTick进行DOM监听来重新初始化echart

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 子组件 父组件引用示例 值得注意的是:由于echart数据依赖DOM更新,再次赋值时需要重新初始化echart,在...
    追寻1989阅读 667评论 0 0
  • 一:什么是闭包?闭包的用处? (1)闭包就是能够读取其他函数内部变量的函数。在本质上,闭包就 是将函数内部和函数外...
    xuguibin阅读 10,025评论 1 52
  • 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: 实例生命周期钩子 每个 Vue 实例...
    Timmy小石匠阅读 1,437评论 0 11
  • 风肆无忌惮的刮 远处天边乌云密布 天马上就要下雨了 路上的行人匆匆的往回走 鸟儿也叽叽喳喳的回巢去 突然格外想念远...
    落之痕阅读 296评论 0 4
  • 如果有一种幸福 我相信不是情人的999朵玫瑰 应该是父亲栽种的玫瑰和栀子 是母亲拍下的一幅幅没有构图没有精修的 半...
    尼龙小姐的日记阅读 298评论 2 2

友情链接更多精彩内容