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

前言

我在工作中使用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) returninstance.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) returninstance.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 = nullclearTimeout(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><divref="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) returninstance.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 = nullclearTimeout(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.mzph.cn/pingmian/20398.shtml

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

相关文章

【Java】还有人不懂继承?25 个 Case 包教包会

还有人不懂继承&#xff1f;25 个 Case 包教包会 1.Implement single inheritance2.Implement multilevel inheritance3.Implement hierarchical inheritance4.Override a base class method into a derived class5.Demonstrate the protected access specifier6.Create an Stu…

《面试笔记》——MySQL终结篇30

三大范式&#xff1f; 第一范式&#xff1a;字段具有原子性&#xff0c;不可再分&#xff08;字段单一职责&#xff09; 第二范式&#xff1a;满足第一范式&#xff0c;每行应该被唯一区分&#xff0c;加一列存放每行的唯一标识符&#xff0c;称为主键&#xff08;都要依赖主…

10- Redis 键值对数据库是怎么实现的?

在开始将数据结构之前&#xff0c;先给介绍下 Redis 是怎样实现键值对&#xff08;key-value&#xff09;数据库的。 Redis 的键值对中的 key 就是字符串对象&#xff0c;而 value 可以是字符串对象&#xff0c;也可以是集合数据类型的对象&#xff0c;比如 List 对象&#xf…

Django序列化器中is_valid和validate

今天上班的时候分配了一个任务&#xff0c;是修复前端的一个提示优化&#xff0c;如下图所示&#xff1a; 按照以往的经验我以为可以直接在validate上进行校验&#xff0c;如何抛出一个异常即可 &#xff0c;例如&#xff1a; class CcmSerializer(serializers.ModelSerialize…

体验Photoshop:无需下载,直接在浏览器编辑图片

搜索Photoshop时&#xff0c;映入眼帘的是PS软件下载&#xff0c;自学PS软件需要多长时间&#xff0c;学PS软件有必要报班吗...PS软件的设计功能很多&#xff0c;除了常见的图像处理功能外&#xff0c;还涉及图形、文本、视频、出版等。不管你是平面设计师&#xff0c;UI/UX设计…

Servlet搭建博客系统

现在我们可以使用Servlet来搭建一个动态(前后端可以交互)的博客系统了(使用Hexo只能实现一个纯静态的网页,即只能在后台自己上传博客)。有一种"多年媳妇熬成婆"的感觉。 一、准备工作 首先创建好项目,引入相关依赖。具体过程在"Servlet的创建"中介绍了。…

FreeRTOS【14】软件定时器使用

1.开发背景 基于以上的章节&#xff0c;这个篇章主题是软件定时器使用&#xff0c;能使用 FreeRTOS 的基本都是从裸机 MCU 过来的&#xff0c;基本都知道 MCU 最基本的功能之一就是定时器&#xff0c;确切的说是硬件定时器&#xff0c;外围电路已经构建好的&#xff0c;精度很高…

【实战JVM】-实战篇-05-内存泄漏及分析

【实战JVM】-实战篇-05-内存泄漏及分析 1 内存溢出和内存泄漏1.1 常见场景1.2 解决内存溢出的方法1.2.1 发现问题1.2.1.1 top1.2.1.2 ViusalVM1.2.1.3 arthas1.2.1.4 PrometheusGrafana 1.2.2 堆内存状况对比1.2.3 内存泄漏原因-代码中1.2.3.1 equals()-hashCode()1.2.3.2 内部…

小程序-富文本编辑框的注意事项

富文本编辑框官网位置 表单组件 / editor (qq.com)https://developers.weixin.qq.com/miniprogram/dev/component/editor.html &#xff08;一&#xff09;富文本编辑框的作用 1.适用于一些表单的提交 2.这些表单内容需要自定义图片大小&#xff0c;编辑文字样式 主要用到的是…

【C++】10.list

list这个迭代器是双向迭代器&#xff0c;与vector的迭代器具有很大的区别&#xff0c;主要在于双向迭代器不支持&#xff0b;- 操作 正由于list的双向迭代器&#xff0c;因此<algorithm>中的sort()函数无法使用&#xff0c;list单独实现了一个sort()函数&#xff0c;但效…

统计信号处理基础 习题解答10-5

题目 通过令 并进行计算来重新推导MMSE估计量。提示&#xff1a;利用结果 解答 首先需要明确的是&#xff1a; 上式是关于观测值x 的函数 其次需要说明一下这个结果 和教材一样&#xff0c;我们用求期望&#xff0c;需要注意的是&#xff0c;在贝叶斯情况下&#xff0c;是个…

创刊即王炸?首个IF近7分,稳坐中科院1区!同领域全球第一!

【欧亚科睿学术】 01 期刊基本概况 【期刊类型】经济类SSCI 【出版社】SPRINGER出版社 【期刊概况】IF&#xff1a;8.0-9.0&#xff0c;JCR1区&#xff0c;中科院1区 【版面类型】正刊&#xff0c;仅少量版面 【预警情况】2020-2024年无预警记录 【收录年份】2016年被WO…

Facebook开户|Facebook做落地页的标准和建议

哈喽呀家人们下午好~今天Zoey来跟大家带来Facebook做落地页的标准和建议&#xff01;需要的家人建议点赞收藏啦&#xff01;&#xff01;用户通过点击你的推广链接、搜索引擎搜索结果页面的快照链接、社交媒体中的网页链接、电子邮件中的链接等进入你网站的特定页面&#xff0c…

tcp链接中的三次挥手是什么原因

一、tcp链接中的正常四次挥手过程&#xff1f; 刚开始双方都处于 ESTABLISHED 状态&#xff0c;假如是客户端先发起关闭请求。四次挥手的过程如下&#xff1a; 1、客户端打算关闭连接&#xff0c;此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文&#xff0c;也即 FIN 报文…

pytorch项目实战-分类模型李宏毅 21 机器学习第三次作业代码详解 CNN图片分类任务

CNN 卷积神经网络食物分类任务 前言一、数据集介绍二、CNN模型整体框架三、卷积神经网络代码详解3.1 导入需要使用的包3.2 数据集&#xff0c;数据加载器&#xff0c;数据增强操作3.2.1 数据增强3.2.2 数据集构建3.2.3 加载器构建 3.3 卷积神经网络构建3.4 训练代码3.4.1 半监督…

jmeter多用户登录并退出教程

有时候为了模拟更真实的场景&#xff0c;在项目中需要多用户登录并退出操作&#xff0c;大致参考如下 多用户登录前面已经实现&#xff1a;参考博文 多用户登录并退出jmx文件&#xff1a;百度网盘 提取码&#xff1a;0000 一、多用户退出操作 添加一个setUp线程组&#xff0…

Perplexity 搜索引擎刚刚推出了新的页面功能——维基百科可以扔了

Perplexity 允许用户根据搜索结果创建自定义页面 人工智能搜索引擎初创公司 Perplexity 推出了一项新功能&#xff0c;使其结果更具粘性&#xff0c;允许用户将研究转变为易于共享的页面。页面建立在 Perplexity 中现有的人工智能驱动的搜索功能之上&#xff0c;该功能使用与 …

云服务(ECS)Docker安装vulhub安装详解

本文以xshell进行远程控制 1.以ssh连接云服务器 ssh 服务器名公网ip [D:\~]$ ssh root47.99.138.9 在弹框中输入密码 2.安装docker curl -s http://get.docker.com/ | sh rootiZbp1fm14idjlfp53akni8Z:~# curl -s https://get.docker.com/ | sh # Executing docker insta…

万字长文,小白新手怎么开始做YOLO实验,从零开始教!整体思路在这里,科研指南针!

最近专栏来了很多的新手小白&#xff0c;对科研实验的过程感到困惑和无从下手&#xff0c;这篇文章就来讲解一下整体的科研流程&#xff0c;从选择数据集到发表论文的各个步骤&#xff0c;并针对大家在实验中常犯的错误进行解答。并且为大家提供通向我其他相关博客的指引&#…

激光焊接机作为一种高效、精密的焊接设备

激光焊接机是一种用于材料加工时激光焊接的机器&#xff0c;以下是对其的详细介绍&#xff1a; 1. 定义与别称&#xff1a; 激光焊接机&#xff0c;又常称为激光焊机、镭射焊机&#xff0c;是材料加工激光焊接时用的机器。 2. 工作原理&#xff1a; 激光焊接是利用高能量…