echarts学习:基本使用和组件封装

news2024/12/24 21:33:16

前言

我在工作中使用echarts较少,这就导致每次使用时都要从头再来,这让我很头疼。因此我决心编写一系列文章将我参与工作后几次使用echarts所用到的知识记录下来,以便将来可以快速查阅。

一、基本使用

像我一样的新手,想要入门echarts还是建议要从官方文档的快速上手开始。我在这里会记录其中的几个简要的步骤。

1.安装

NPM

npm install echarts

CDN

<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>

2.项目中引入

注意最新的版本一定要用这种带有as的方式,某些老的博客文章中可能写的是旧版的引入方式。

import * as echarts from 'echarts';

3.绘制图表

使用echarts绘制图表很简单,我把它称为“echarts的三步走战略”:准备容器获取实例设置选项

3.1准备容器

准备容器就是要准备一个element作为放置echarts图表的容器,许多的图表库都有这样的操作。容器元素的作用就是确定图表在我们应用中的位置,以及限制图表的范围,因此容器必须要设置尺寸样式(是谁忘了设置尺寸?哦,原来是我 (*/ω\*) ,那没事了)。

<!-- 记得给容器设置宽高 -->
<div id="main" style="width: 600px;height:400px;"></div>

还有一个需要注意的点是,如果在Vue中使用echarts,有时可能会出现无法获取到dom的情况。想要了解具体的问题情境和解决方法请浏览我的这篇文章:vue3中获取元素DOM的方法

3.2 获取实例

获取实例就是通过echarts.init()工厂方法获取一个echarts实例,init方法接收一个dom(容器dom)返回一个实例。

<template>
  <div ref="container" style="width: 600px; height: 400px"></div>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import * as echarts from 'echarts'

// 容器元素
const container = ref(null)

onMounted(() => {
    // 获取实例
    const chartInstance =  echarts.init(container.value)
})
</script>

3.3 设置选项

最后需要使用echarts实例的setoption方法设置配置项。配置项是echarts的核心,其内容博大精深,想了解更多有关echarts配置项的信息,请查阅echarts配置项手册。

<template>
  <div ref="container" style="width: 600px; height: 400px"></div>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import * as echarts from 'echarts'

// 容器元素
const container = ref(null)

onMounted(() => {
  // 获取实例
  const chartInstance = echarts.init(container.value)
  // 设置选项
  chartInstance.setOption({
    xAxis: {
      type: 'category',
      show: false,
      boundaryGap: false,
    },
    yAxis: {
      show: false,
    },
    series: [
      {
        type: 'line',
        data: [
          620, 432, 220, 534, 790, 430, 220, 320, 532, 320, 834, 690, 530, 220,
          620,
        ],
        areaStyle: {
          color: 'purple',
        },
        lineStyle: {
          width: 0,
        },
        itemStyle: {
          opacity: 0,
        },
        smooth: true,
      },
    ],
    grid: {
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
    },
  })
})
</script>

最后绘出如下的图表

二、封装echarts组件

大概在一年前我在公司的某个项目中看到了封装的echarts组件,之后我也曾经研究过,但最后都半途而废了。如今我重头再来,希望这次可以成功。

1.为什么要封装echarts组件?

echarts组件的主要作用是对上面所提到的 "三步走战略" 进行一个封装,这样我们就不需要重复去执行这些步骤了。每次绘图时只需要给echarts组件传递配置项即可。

2.echarts组件需要实现的功能

我封装的echarts组件准备实现以下的功能:

基础功能

优化功能

拓展功能

  1. 基本的“三步走战略”
  2. 销毁实例
  3. 图表的重绘
  1. 图表尺寸的自适应(当页面大小变化时,图表尺寸跟着变化)
  2. 图表宽高可设置
  3. 展示loading动画
  1. 侦听图表的点击事件(这里也可以补充其它需要的事件)
  2. 暴露实例方法

3.封装基本功能

再复习一下,使用echarts绘制图表的“三步走战略”是:

  1. 准备容器
  2. 获取实例
  3. 设置选项
<template>
  <div ref="container" style="width: 600px; height: 400px"></div>
</template>

<script setup>
import { onMounted, onUnmounted, ref ,nextTick} from 'vue'
import * as echarts from 'echarts'

// props
const props = defineProps({
  option: {
    type: [Object, null],
    require: true,
  }, //配置项
})

// 容器元素
const container = ref(null)
// 实例
const instance = ref(null)
// 初始化
function init() {
  if (!container.value) return

  //查看容器上是否已经挂载了echarts实例 , 如果已挂载就获取并使用该实例,如果未挂载就进行初始化
  instance.value = echarts.getInstanceByDom(container.value)
  if (!instance.value) {
    instance.value = echarts.init(container.value)
  }
   draw()
}
// 绘制图表
function draw() {
  if (!props.option || !instance.value) return
  instance.value.setOption(props.option)
}

onMounted(() => {
  nextTick(() => {
    init()
  })
})
</script>

考虑容器已被挂载echarts实例的情况

上面的代码中值得注意的一个点是,在初始化的时候考虑了容器可能已被挂载了实例的情况。

为了兼容这种情况就首先使用echarts.getInstanceByDom获取容器上的实例。如果容器已有实例就使用该实例,如果容器上没有实例就进行初始化。

instance.value = echarts.getInstanceByDom(container.value)
if (!instance.value) {
  instance.value = echarts.init(container.value)
}

4.将echats实例代理为响应式对象可能带来的风险

将echarts实例保存为响应式对象,可能会造成一系列意外的问题。因此在这里建议将echarts组件中的实例使用普通变量或者shallowRefshallowReactivemarkRaw等API进行保存。

我是使用了shallowRef来取代原来的ref:

// 实例
const instance = shallowRef(null)

想要了解更多的相关信息,可以浏览我写的这篇文章 将echats实例代理为响应式对象可能带来的风险 。

5.销毁实例

当echarts组件被卸载时,我们应当调用dispose方法销毁实例,以防止可能得内存泄漏。

onUnmounted(()=>{
  instance.value?.dispose()
})

6.图表重绘

我们希望当echarts组件中接收到的一些props(例如option)发生变化时可以重新绘制图表。

我一开始的写法是这样的

function draw() {
  if (!props.option || !instance.value) return
  // 先清空实例
  instance.value && instance.value.clear()
  // 然后再重新绘制
  instance.value.setOption(props.option)
}

watch(props,()=>{
  draw()
})

后来发现只需要在调用setOption方法时将其notMerge选项设为true,就会自动的先清空组件然后再根据传入的配置项渲染新的图表。

function draw() {
  if (!props.option || !instance.value) return
  instance.value.setOption(props.option, {
    notMerge: true,
  })
}

watch(props,()=>{
  draw()
})

7.实现图表的自适应

我们希望当页面的尺寸发生变化时,图表的尺寸也会跟着变化。我实现这一功能的基本思路如下图所示:

我使用ResizeObserver监听容器元素的尺寸变化,当容器的尺寸变化时,调用chartInstance.resize方法重置图表尺寸。想了解与图表自适应相关的详细内容,请参考我的文章:图表自适应。


const resizeObserver = shallowRef(null) // 元素尺寸侦听器
const debounceTimer = ref(null) //防抖计时器id

// 重置图表尺寸
function resize() {
  clearTimeout(debounceTimer.value)
  debounceTimer.value = setTimeout(() => {
    instance.value?.resize({
      animation: {
        duration: 300,
      },
    })
    debounceTimer.value = null
  }, 300)
}
resizeObserver.value = new ResizeObserver(resize)

onMounted(() => {
  nextTick(() => {
    resizeObserver.value.observe(container.value)
  })
})

onUnmounted(() => {
  resizeObserver.value?.disconnect()
  resizeObserver.value = null
  clearTimeout(debounceTimer.value)
  debounceTimer.value = null
})

8.图表宽高可设置

我们希望可以在使用echarts组件的时候自定义图表的宽高。想要实现这一功能也很简单,只需要增加两个prop即可。

const props = defineProps({
  width: {
    type: String,
    default: '300px',
  },
  height: {
    type: String,
    default: '200px',
  },
})
<div ref="container" :style="{width: props.width, height: props.height}"></div>

9.显示loading动画

很多时候图表数据都是异步的,获取数据需要时间,此时就希望在数据获取的时候给用户展现loading动画效果,以提升用户体验。

以前我都是借助于第三方组件的的loading组件来实现这一功能的(例如Ant Design 的 <a-spin> 或者 Element-ui 的 v-loading)。

现在才知道其实echarts是有自带的loading动画效果的,可以通过实例的showLoadinghideLoading方法控制。现在我们就可以借助这两个方法来实现图表的loading效果:

const props = defineProps({
  loading: {
    type: Boolean,
    default: false,
  },
})

// loading动画
watchEffect(() => {
  props.loading ? instance.value?.showLoading() : instance.value?.hideLoading()
})

让我们来看一下最终的效果:

10.侦听图表的事件

echarts图表有一套自己的事件系统,当我们需要实现一些与图表的交互效果的时候,可能就需要用到这些事件。我们可以在echarts组件中提前封装这些事件以便在将来使用。例如我添加一个图表的点击事件:

const props = defineProps({
  // 省略...
  onClick: {
    type: Function,
  },
})

function init() {
  // 省略...

  addListeningChartEvent()
}

// echarts事件绑定
function addListeningChartEvent() {
  // 点击事件
  props.onClick &&
    instance.value?.on('click','series', (e) => {
      props.onClick(e, instance.value, props.option)
    })
}

11.暴露echarts实例

上面提到了在组件中侦听图表事件,但授人以鱼不如授人以渔,比起琐碎的封装事件,不如直接将echarts实例暴露给使用者。

我们可以参考Vue官方文档了解如何从组件中暴露属性和方法:

于是我使用defineExpose方法在将我组件中的实例暴露出来:

defineExpose({
  getInstance: () => instance.value,
  resize,
  draw,
})

12.完整代码

<template>
  <div
    ref="container"
    :class="props.className"
    :style="{ width: props.width, height: props.height }"
  ></div>
</template>

<script setup>
import {
  nextTick,
  onMounted,
  onUnmounted,
  ref,
  shallowRef,
  watch,
  watchEffect,
} from 'vue'
import * as echarts from 'echarts'

// props
const props = defineProps({
  option: {
    type: [Object, null],
    require: true,
  }, //配置项
  width: {
    type: String,
    default: '300px',
  },
  height: {
    type: String,
    default: '200px',
  },
  className: {
    type: String,
    default: 'cl-chartCom',
  },
  loading: {
    type: Boolean,
    default: false,
  },
  onClick: {
    type: Function,
  },
})

const container = ref(null) // 容器元素
const instance = shallowRef(null) // 实例
const resizeObserver = shallowRef(null) // 元素尺寸侦听器
const debounceTimer = ref(null) //防抖计时器id

// 初始化
function init() {
  if (!container.value) return

  //查看容器上是否已经挂载了echarts实例 , 如果已挂载就获取并使用该实例,如果未挂载就进行初始化
  instance.value = echarts.getInstanceByDom(container.value)
  if (!instance.value) {
    instance.value = echarts.init(container.value)
  }

  // 绘制图表
  draw()
  // 侦听图表事件
  addListeningChartEvent()
}
// 绘制图表
function draw() {
  if (!props.option || !instance.value) return
  instance.value.setOption(props.option, {
    notMerge: true,
  })
}

// 图表自适应
// 重置图表尺寸
function resize() {
  clearTimeout(debounceTimer.value)
  debounceTimer.value = setTimeout(() => {
    instance.value?.resize({
      animation: {
        duration: 300,
      },
    })
    debounceTimer.value = null
  }, 300)
}
resizeObserver.value = new ResizeObserver(resize)

// 重绘图表
watch(props, () => {
  nextTick(() => {
    draw()
  })
})

// loading动画
watchEffect(() => {
  props.loading ? instance.value?.showLoading() : instance.value?.hideLoading()
})

// echarts事件绑定
function addListeningChartEvent() {
  // 点击事件
  props.onClick &&
    instance.value?.on('click', 'series', (e) => {
      props.onClick(e, instance.value, props.option)
    })
}

onMounted(() => {
  nextTick(() => {
    init()
    resizeObserver.value.observe(container.value)
  })
})
onUnmounted(() => {
  instance.value?.dispose()
  resizeObserver.value?.disconnect()
  resizeObserver.value = null
  clearTimeout(debounceTimer.value)
  debounceTimer.value = null
})

defineExpose({
  getInstance: () => instance.value,
  resize,
  draw,
})
</script>

参考资料

  1. Vue3 封装 ECharts 通用组件_vue3如何封装echarts-CSDN博客
  2. Vue3 封装ECharts 组件 抽离复用 包含图表随着窗口宽高变化而变化-CSDN博客
  3. echartsInstance.setOption - Apache ECharts
  4. echartsInstance.showLoading - Apache ECharts
  5. events.鼠标事件.click - Apache ECharts
  6. 模板引用-Vue.js

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1789088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【方法论】钟澄国家杰青 鲸吞法 写文献综述、大论文框架必备

Xlab2020的个人空间-Xlab2020个人主页-哔哩哔哩视频 老师指南 就是1号文件有了后&#xff0c;也就是【】概括了之后&#xff0c;我们会运行下程序&#xff08;程序我会让学生share&#xff09;。然后程序会执行这么一个操作&#xff0c;复制下【】内容&#xff0c;然后在第二个…

在Windows11系统上搭建SFTP服务器

利用OpenSSH搭建SFTP服务器 下载安装部署OpenSSH创建一个测试账户测试链接为SFTP用户配置根目录下载安装部署OpenSSH 参考链接 部署完启动服务要使用管理员模式。 net start sshd创建一个测试账户 使用PC的微软账户是访问不了SFTP的。 需要使用被微软账户覆盖掉的系统账户和…

ATA-3080C功率放大器的基本原理是什么

功率放大器是一种电子设备&#xff0c;用于将输入信号的功率增加到更高的水平&#xff0c;以便驱动负载或输出设备。它在许多应用中都起着重要作用&#xff0c;包括音频放大、无线通信、雷达系统和工业控制等。 功率放大器的基本原理可以通过两个关键概念来解释&#xff1a;放大…

【机器学习】机器学习与推荐系统在电子商务中的融合应用与性能优化新探索

文章目录 引言机器学习与推荐系统的基本概念机器学习概述监督学习无监督学习强化学习 推荐系统概述基于内容的推荐协同过滤混合推荐 机器学习与推荐系统的融合应用用户行为分析数据预处理特征工程 模型训练与评估模型训练模型评估 个性化推荐基于用户的协同过滤基于商品的协同过…

汇凯金业:开盘买入还是收盘时买入好

在股票交易中&#xff0c;选择在开盘时还是收盘时进行买入操作&#xff0c;取决于投资者的策略和市场状况。以下是两种策略的优缺点及其适用情境&#xff1a; 开盘时买入 优点&#xff1a; 快速入场&#xff1a;如果夜间或开盘前出现了重大利好消息&#xff0c;及时在开盘时…

CRM客户关系管理系统功能概览

CRM客户关系管理系统是一款集成了多种功能的客户管理工具&#xff0c;旨在帮助企业高效地管理客户关系&#xff0c;提升销售业绩。以下是该系统的功能模块及描述&#xff1a; 一、待办事项 今日需联系客户&#xff1a;提供客户列表&#xff0c;支持多条件查询&#xff0c;包括客…

唯众智联网(AIoT)应用开发教学实训解决方案

一、引言 随着信息技术的飞速发展&#xff0c;物联网&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;技术逐渐融合&#xff0c;形成了智联网&#xff08;AIoT&#xff09;这一新兴领域。智联网通过智能化设备、传感器、云计算等技术手段&#xff0c;实现了数…

对接专有钉钉(浙政钉)登陆步骤

背景 因为项目需要对接浙政钉&#xff0c;我想应该和之前对接阿里云的钉钉登陆钉钉登陆类似&#xff0c;就上网搜索看看&#xff0c;出现了个专有钉钉的概念&#xff0c;就一时间搞不清楚&#xff0c;钉钉&#xff0c;专有钉钉&#xff0c;浙政钉的区别&#xff0c;后续稍微理…

三维重建,谁才是顶流?

3DGS技术是近年来计算机视觉领域最具突破性的研究成果之一。它不仅在学术界引起了广泛关注&#xff0c;成为计算机视觉、SLAM等领域的研究热点&#xff0c;而且每天都有大量基于Gaussian Splatting的新研究问世。此外&#xff0c;3DGS技术在商业应用方面也取得了显著进展&#…

PPT设置为本框的默认格式以及固定文本框

调整文本框固定位置 双击文本框之后勾选如下三个位置 设置文本框为默认 在调整好文本框的基本性质后&#xff0c;设置为默认即可

2024最新python入门教程|python安装|pycharm安装

前言&#xff1a;在安装PyCharm之前&#xff0c;首先需要明确PyCharm是一款功能强大的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;由JetBrains公司开发。PyCharm旨在通过提供智能代码补全、语法高亮、代码检查、快速导航和重构等丰富的编码辅助工具&#xff0c…

BypassD: Enabling fast userspace access to shared SSDs——论文泛读

ASPLOS 2024 Paper 论文阅读笔记整理 问题 现代存储设备&#xff0c;如Optane NVMe SSD&#xff0c;提供几微秒的超低延迟和每秒数千GB的高带宽&#xff0c;导致内核软件I/O堆栈是开销的主要来源。例如&#xff0c;Optane SSD可以在4&#x1d707;s内返回4KB块&#xff0c;而…

金融风控模型论文定制服务_研究生博士生毕业论文_小论文_中文核心_CCF_EI会议_AI_人工智能_机器学习

金融风控论文定制服务范围 论文复现案例包括但不限于&#xff1a; 1.个人信贷风控模型 1.1.German Credit德国信用数据集风控模型 1.2.Give me some credit风控模型 1.3.lending club风控信贷模型&#xff08;美国最大P2P平台&#xff0c;目前已转线上银行&#xff09; 1…

针对AlGaN/GaN高电子迁移率晶体管的显式表面电势计算和紧凑电流模型

来源&#xff1a;An Explicit Surface Potential Calculation and Compact Current Model for AlGaN/GaN HEMTs&#xff08;EDL 15年&#xff09; 摘要 在本文中,我们提出了一种新的紧凑模型,用于基于费米能级和表面电位的显式解来描述AlGaN/GaN高电子迁移率晶体管。该模型计算…

Matlab2010安装注册+激活(保姆级教程)

目录 一、软件安装 二、软件激活 三、软件测试 Matlab2010压缩包: 链接&#xff1a;https://pan.baidu.com/s/1bX4weZ0nC-4zlDLUiSKcRQ?pwdxljj 提取码&#xff1a;xljj 一、软件安装 1.解压所给压缩包&#xff0c;目录双击setup.exe打开. (如果用户名为中文则会遇到这个…

使用Flutter开发APP的问题

在使用Flutter进行APP开发时&#xff0c;尽管Flutter提供了许多优势和便利&#xff0c;但也存在一些常见问题和挑战。以下是开发过程中可能遇到的问题以及应对方法&#xff0c;通过充分理解和应对这些问题&#xff0c;可以更好地利用Flutter的优势&#xff0c;开发出高质量的跨…

儿童护眼灯买什么牌子质量好又实惠?儿童品牌台灯质量前十的款式

儿童护眼灯买什么牌子质量好又实惠&#xff1f;在当今时代&#xff0c;电子设备在我们的日常生活中扮演着越来越重要的角色。然而&#xff0c;长时间使用这些设备可能会增加眼睛疲劳和近视的风险。为了解决这一问题&#xff0c;护眼台灯应运而生&#xff0c;并逐渐成为许多家庭…

人工智能_机器学习096_PCA主成分分析降维算法_PCA降维原理_介绍和使用_模式识别_EVD特征值分解_SVD奇异值分解---人工智能工作笔记0221

首先我来看PCA降维,可以看到在图像处理中经常用到PCA,经过对数据进行降维可以去除数据噪声,发现数据中的模式,也就是 发现数据的规律. 这里的模式识别就是 机器学习中的一个分支 就是在数据中找规律的意思 我们使用代码看一下 from sklearn.docomposition import PCA from skl…

通配符SSL证书:保障多子域名安全的明智之选

在数字化时代&#xff0c;网络安全日益成为企业和个人关注的焦点。SSL证书作为保障网络安全的重要手段之一&#xff0c;其种类和功能也日趋多样化。其中&#xff0c;通配符证书&#xff08;也称为泛域名SSL证书&#xff09;以其独特的功能和广泛的应用场景&#xff0c;成为网络…

vue2 bug求助!!!(未解决,大概是浏览器缓存的问题或者是路由的问题)

我的vue2项目出现了一个超级恶心的bug 过程&#xff1a; 1 操作流程&#xff1a;页面a点击a标签->到页面b->页面b用户退出刷新页面->点击浏览器的返回按钮返回上一页 2 结果&#xff1a;返回页面后页面没有刷新导致用户名还显示着&#xff0c;页面没有发生任何变化&a…