内容

记录组件封装思路
实现ECharts 组件的封装

写在前面

写在前面:对于愈来愈火的前端框架,用起来着实是让人很舒心。对于大型项目来说,组件化思想更是尤为重要,那么学会组件的封装自然是必不可少。本文浅谈一下封装组件的思路以及心得,希望对大家有所帮助。

1. 封装思路

1.1 观察文档,考虑组件需要的基本参数

每个组件需要的参数都很固定,包含:基本参数+独有参数

我们要做的就是:分离基本参数,父组件向子组件传递基本参数和独有参数

1.2 参数筛选,分为父组件传来的参数和自身参数

父组件传递的一般为基本参数,自身的参数为独有参数

1.3 完善组件,观察个别处与理想有无出入,更改配置项达到理想态
1.4 细节优化,考虑多种场景下,图表自适应处理

根据假设场景,做相应处理

2. ECharts 组件的封装

2.1 通过观察文档;常用的 ECharts组件都包含的配置项为: series,一些带坐标轴的图表都包含配置项:xAxisyAxis
2.2 我们在组件的 props 中接收父组件传递的参数,根据参数判断其是否有坐标轴,然后动态的渲染不同类型的图表(通过计算属性判断)
2.3 在ECharts 组件中定义两个方法:1、渲染组件的方法;2、渲染数据的方法(写在组件渲染前)
2.4 通过侦听器来监控 ECharts 组件接收的值是否放生改变,若改变就调用组件的渲染方法(达到视图的渲染)

具体封装代码(ECharts.vue)

<template>
  <div style="height:100%" ref="echart"></div>
</template>

<script>
import echarts from 'echarts';
export default {
  props: {
    // 接收父组件传递的ECharts 数据
    chartData: {
      //定义出需要动态传递的参数
      type: Object,
      default() {
        return {
          xData: [],
          series: [],
        };
      },
    },
    isAxisChart: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      //返回要渲染的数据
      echart: null,
      //# 含坐标轴的图表
      axisOption: {
        xAxis: {
          //x轴数据
          type: 'category',
          data: [],
        },
        yAxis: [
          //y轴数据(根据series 中的date 渲染)
          {
            type: 'value',
          },
        ],
        series: [], //数据渲染的结构
      },
      //# 不含坐标轴的图表
      noAxisOption: {
        series: [],
      },
    };
  },
  computed: {
    //计算属性判断 是否渲染坐标轴
    options() {
      return this.isAxisChart ? this.axisOption : this.noAxisOption;
    }
  },
  watch: {
    chartData: {
      handler() {
        this.initChart();
      },
      deep: true, // 需要deep属性对 对象进行深度监听
    }
  },
  methods: {
    initChart() {
      //# 初始化容器时,初始化数据
      this.initChartData();
      //初始化容器(图标)
      if (this.echart) {
        //若容器存在,直接渲染数据(官方api 写入配置)
        this.echart.setOption(this.options);
      } else {
        this.echart = echarts.init(this.$refs.echart);
        this.echart.setOption(this.options);
      }
    },
    initChartData() {
      //初始化数据
      if (this.isAxisChart) {
        //#把自身的数据替换成父组件传过来的数据
        this.axisOption.xAxis.data = this.chartData.xData;
        this.axisOption.series = this.chartData.series;
      } else {
        this.noAxisOption.series = this.chartData.series;
      }
    },
  },
};
</script>
<style lang='less' scoped>
</style>

父组件代码:

 <el-card shadow="hover">
            <echart style="height:260px" :chartData="echartData.user"></echart>
 </el-card>
 <el-card shadow="hover">
    		<!-- 要用isAxisChart 来告诉子组件渲染的图表格式 -->
 			<echart style="height:260px" :chartData="echartData.video" :isAxisChart = "false"></echart>
 </el-card>

注意:对于 ECharts 组件中的参数格式,可根据 ECharts 官网进行配置—ECharts官网

last

优化后的 ECharts 组件

<template>
  <div style="height:100%" ref="echart"></div>
</template>

<script>
import echarts from 'echarts';
export default {
  props: {
    // 接收父组件传递的ECharts 数据
    chartData: {
      //定义出需要动态传递的参数
      type: Object,
      default() {
        return {
          xData: [],
          series: [],
        };
      },
    },
    isAxisChart: {
      type: Boolean,
      default: true,
    },
  },
  computed: {
    //计算属性判断 是否渲染坐标轴
    options() {
      return this.isAxisChart ? this.axisOption : this.noAxisOption;
    },
    collapse() {
      return this.$store.state.isCollapse;
    },
  },
  data() {
    return {
      //返回要渲染的数据
      echart: null,
      //# 含坐标轴的图表
      axisOption: {
        tooltip: {
          tirgger: 'item',
        },
        legend: {
          textStyle: {
            color: '#333',
          },
        },
        xAxis: {
          //x轴数据
          type: 'category',
          data: [],
          axisLine: {
            lineStyle: {
              color: '#33CC00',
            },
          },
        },
        yAxis: [
          //y轴数据(根据series 中的date 渲染)
          {
            type: 'value',
          },
        ],
        // 配置展示数据的颜色
        color: [
          '#CC66FF',
          '#33FF00',
          '#663300',
          '#FF3300',
          '#999900',
          '#FFFF00',
        ],
        series: [], //数据渲染的结构
      },
      //# 不含坐标轴的图表
      noAxisOption: {
        tooltip: {
          tirgger: 'item',
        },
        legend: {
          textStyle: {
            color: '#333',
          },
        },
        color: [
          '#CC66FF',
          '#33FF00',
          '#663300',
          '#FF3300',
          '#999900',
          '#FFFF00',
        ],
        series: [],
      },
    };
  },
  watch: {
    chartData: {
      handler() {
        this.initChart();
      },
      deep: true,
    },
    collapse() {
      setTimeout(this.listenResize, 300); // 监听折叠变量(实现折叠响应式变化图标)
    },
  },
  methods: {
    initChart() {
      //# 初始化容器时,初始化数据
      this.initChartData();
      //初始化容器(图标)
      if (this.echart) {
        //若容器存在,直接渲染数据(官方api 写入配置)
        this.echart.setOption(this.options);
      } else {
        this.echart = echarts.init(this.$refs.echart);
        this.echart.setOption(this.options);
      }
    },
    initChartData() {
      //初始化数据
      if (this.isAxisChart) {
        //#把自身的数据替换成父组件传过来的数据
        this.axisOption.xAxis.data = this.chartData.xData;
        this.axisOption.series = this.chartData.series;
      } else {
        this.noAxisOption.series = this.chartData.series;
      }
    },
    listenResize() {
      //# 监听浏览器尺寸,做出响应式展示
      this.echart ? this.echart.resize() : '';
    },
  },
  mounted() {
    // 挂载钩子,判断窗口大小
    window.addEventListener('resize', this.listenResize);
  },
  destroyed() {
    // 挂载卸载钩子,防止内存泄漏
    window.removeEventListener('resize', this.listenResize);
  },
};
</script>
<style lang='less' scoped>
</style>

注意:优化后的组件,新增了自定义颜色以及响应式的处理

心得

对于大部分组件的封装与 ECharts 组件的封装大同小异,我们要找到基本参数,然后逐步解析,本文结束。

愿所有的美好都与你环环相扣,加油。
Logo

前往低代码交流专区

更多推荐