vue3封装echarts

​前期回顾    ​        

css自定义属性_0.活在风浪里的博客-CSDN博客css自定义属性https://blog.csdn.net/m0_57904695/article/details/126351923?spm=1001.2014.3001.5501

目录

vue2封装

 子组件

页面使用

 vue3封装

 子组件

页面使用


vue2封装

 

 子组件

<template>
  <div :id="uuid" :style="style"></div>
</template>

<script>
import * as echarts from "echarts";

const idGen = () => {
  return new Date().getTime();
};

export default {
  props: {
    height: {
      type: String,
      default: "400px",
    },
    width: {
      type: String,
      default: "600px",
    },

    options: {
      type: Object,
      default: null,
    },
  },

  data() {
    return {
      uuid: null,
      myChart: null,
    };
  },

  watch: {
    width(a, b) {
      if (this.myChart) {
      // 这里需要异步才能生效
        setTimeout(() => {
          this.myChart.resize({
            animation: {
              duration: 500,
            },
          });
        }, 0);
      }
    },

    options() {
      if (this.myChart) {
        // notMerge 可选。是否不跟之前设置的 option 进行合并。默认为 false。即表示合并。
        //合并的规则,详见 组件合并模式。如果为 true,表示所有组件都会被删除,然后根据新 option 创建所有新组件
        this.myChart.setOption(this.options, {
          notMerge: true,
        });
      }
    },
  },

  computed: {
    style() {
      return {
        height: this.height,
        width: this.width,
      };
    },
  },

  created() {
    this.uuid = idGen();
  },

  mounted() {
    // 准备实例
    this.myChart = echarts.init(document.getElementById(this.uuid));

    // 应用配置项
    this.myChart.setOption(this.options);
  },
};
</script>

页面使用

<template>
  <div id="app">
    <MyEcharts :options="options" :width="width"></MyEcharts>
    <button @click="changeWidth">changeWidth</button>
    <button @click="changeOpt">changeOpt</button>
  </div>
</template>

<script>
import MyEcharts from "./components/MyEcharts.vue";
import { options1, options2 } from "./options";

export default {
  name: "App",
  components: {
    MyEcharts,
  },
  data() {
    return {
      options: options1,
      width: "600px",
    };
  },
  methods: {
    changeWidth() {
      if (this.width == "600px") {
        console.log(1);
        this.width = "800px";
      } else {
        console.log(2);
        this.width = "600px";
      }
    },
    changeOpt() {
      if (this.options == options1) {
        this.options = options2;
      } else {
        this.options = options1;
      }
    },
  },
};
</script>

 vue3封装

 

 子组件

<template>
  <div :id="uid" :style="style"></div>
</template>
<script setup>
import { defineProps, defineEmits, onMounted, reactive, ref } from "vue";
const emits = defineEmits([]);
import * as echarts from "echarts";

// 因为是封装的组件,会多次调用,id不能重复,要在初始化之前写,不然会报错dom为定义
let uid = ref(null);
onBeforeMount(() => {
  uid.value = `echarts-uid-${parseInt(Math.random() * 1000000)}`;
  // 也可以用毫秒数作为id
  // uid.value = `echarts-uid-${new Date().getTime()}`;
});

onMounted(() => {
  var myChart = echarts.init(document.getElementById(uid.value));
  // 在template中可以直接取props中的值,但是在script中不行,因为script是在挂载之前执行的
  myChart.setOption(props.myOption, {
    notMerge: true, //不和之前的option合并
  });
  // 监听页面的大小
  window.addEventListener("resize", () => {
    myChart.resize({
      animation: {
        duration: 300,
      },
    });
  });
});

const props = defineProps({
  style: {
    type: Object,
    default: () => ({
      width: "600px",
      height: "400px",
    }),
  },
  myOption: {
    type: Object,
    default: () => ({}),
  },
});
</script>
<style lang="scss" scoped></style>

页面使用

<template>
  <div class="heder">
    <my-chart :my-option="chartData"></my-chart>
    <my-chart :my-option="chartData2"></my-chart>
  </div>
  <div class="heder">
    <my-chart :my-option="chartData3"></my-chart>
    <my-chart :my-option="chartData4"></my-chart>
  </div>
</template>
<script setup>
import myChart from "comp/myEcharts/index.vue";
import {
  defineProps,
  defineEmits,
  onMounted,
  reactive,
  ref,
  toRefs,
} from "vue";
let category = [];
let dottedBase = +new Date();
let lineData = [];
let barData = [];
for (let i = 0; i < 20; i++) {
  let date = new Date((dottedBase += 3600 * 24 * 1000));
  category.push(
    [date.getFullYear(), date.getMonth() + 1, date.getDate()].join("-")
  );
  let b = Math.random() * 200;
  let d = Math.random() * 200;
  barData.push(b);
  lineData.push(d + b);
}
let state = reactive({
  chartData: {
    tooltip: {
      trigger: "item",
    },
    legend: {
      top: "5%",
      left: "center",
    },
    series: [
      {
        name: "Access From",
        type: "pie",
        radius: ["40%", "70%"],
        avoidLabelOverlap: false,
        itemStyle: {
          borderRadius: 10,
          borderColor: "#fff",
          borderWidth: 2,
        },
        label: {
          show: false,
          position: "center",
        },
        emphasis: {
          label: {
            show: true,
            fontSize: "40",
            fontWeight: "bold",
          },
        },
        labelLine: {
          show: false,
        },
        data: [
          { value: 1048, name: "Search Engine" },
          { value: 735, name: "Direct" },
          { value: 580, name: "Email" },
          { value: 484, name: "Union Ads" },
          { value: 300, name: "Video Ads" },
        ],
      },
    ],
  },
  chartData2: {
    title: [
      {
        text: "Radial Polar Bar Label Position (middle)",
      },
    ],
    polar: {
      radius: [30, "80%"],
    },
    radiusAxis: {
      max: 4,
    },
    angleAxis: {
      type: "category",
      data: ["a", "b", "c", "d"],
      startAngle: 75,
    },
    tooltip: {},
    series: {
      type: "bar",
      data: [2, 1.2, 2.4, 3.6],
      coordinateSystem: "polar",
      label: {
        show: true,
        position: "middle",
        formatter: "{b}: {c}",
      },
    },
    animation: false,
  },
  chartData3: {
    // option
    backgroundColor: "#0f375f",
    tooltip: {
      trigger: "axis",
      axisPointer: {
        type: "shadow",
      },
    },
    legend: {
      data: ["line", "bar"],
      textStyle: {
        color: "#ccc",
      },
    },
    xAxis: {
      data: category,
      axisLine: {
        lineStyle: {
          color: "#ccc",
        },
      },
    },
    yAxis: {
      splitLine: { show: false },
      axisLine: {
        lineStyle: {
          color: "#ccc",
        },
      },
    },
    series: [
      {
        name: "line",
        type: "line",
        smooth: true,
        showAllSymbol: true,
        symbol: "emptyCircle",
        symbolSize: 15,
        data: lineData,
      },
      {
        name: "bar",
        type: "bar",
        barWidth: 10,
        itemStyle: {
          borderRadius: 5,
        },
        data: barData,
      },
      {
        name: "line",
        type: "bar",
        barGap: "-100%",
        barWidth: 10,
        z: -12,
        data: lineData,
      },
      {
        name: "dotted",
        type: "pictorialBar",
        symbol: "rect",
        itemStyle: {
          color: "#0f375f",
        },
        symbolRepeat: true,
        symbolSize: [12, 4],
        symbolMargin: 1,
        z: -10,
        data: lineData,
      },
    ],
  },
  chartData4: {
    title: [
      {
        text: "Radial Polar Bar Label Position (middle)",
      },
    ],
    polar: {
      radius: [30, "80%"],
    },
    radiusAxis: {
      max: 4,
    },
    angleAxis: {
      type: "category",
      data: ["a", "b", "c", "d"],
      startAngle: 75,
    },
    tooltip: {},
    series: {
      type: "bar",
      data: [2, 1.2, 2.4, 3.6],
      coordinateSystem: "polar",
      label: {
        show: true,
        position: "middle",
        formatter: "{b}: {c}",
      },
    },
    animation: false,
  },
});
const { chartData, chartData2, chartData3, chartData4 } = toRefs(state);
</script>
<style lang="scss" scoped>
.heder {
  display: flex;
}
</style>

总结:

封装代码不多,只要是echarts的数据多!真实项目按照公司结构在优化,

猜你喜欢

转载自blog.csdn.net/m0_57904695/article/details/126367109