Vue3 手把手按需引入 Echarts

您所在的位置:网站首页 vue如何用echarts引入图表 Vue3 手把手按需引入 Echarts

Vue3 手把手按需引入 Echarts

2024-07-16 05:32| 来源: 网络整理| 查看: 265

背景:新项目采用 Vue3 作为前端项目框架,避免不了要使用 echarts,但是在使用的时候,出现了与 Vue2 使用不一样的地方,所以特别记下来,希望给到有需要的同学一些帮助。

下载Echarts依赖 # 自己使用的yarn yarn add echarts # or npm install echarts --save # or # 有淘宝镜像的可以选择 (安装速度快) cnpm install echarts --save 创建按需引入的配置文件 echarts.ts(文件名称自定义)及进行配置 在你自己需要的目录下创建引入 eachrts 配置的文件,我是在 src/utils 目录下创建的 echarts.ts 文件(根据你自己的需求)在echarts.ts文件中引入echarts相关配置,网上有很多教程,但这里还是再啰嗦写一下,做戏做全套,一条龙服务。(看到最后有用给个点赞+收藏) // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。 import * as echarts from "echarts/core"; /** 引入柱状图 + 折线图 + 饼图,图表后缀都为 Chart,一般常用的就这三个,如果还需要其他的,就自行添加 */ import { BarChart, LineChart, PieChart } from "echarts/charts"; // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component import { TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, ToolboxComponent, LegendComponent, } from "echarts/components"; // 标签自动布局,全局过渡动画等特性 import { LabelLayout, UniversalTransition } from "echarts/features"; // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步 import { CanvasRenderer } from "echarts/renderers"; // 注册必须的组件 echarts.use([ TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, ToolboxComponent, LegendComponent, LabelLayout, UniversalTransition, CanvasRenderer, BarChart, LineChart, PieChart, ]); // 导出 export default echarts; 根目录 main.ts 文件引入创建的配置文件 echarts.ts

项目另外采用了 Pinia + ElementPlus + ElementPlus(图标),引入方式都在下面,希望能够得到有需要的朋友帮助。

最重要的是要看本次引入echarts相关配置部分,注释也写好了,大家可以参考一下。

import { createApp } from "vue"; import { createPinia } from "pinia"; // 引入Element-plus import ElementPlus from "element-plus"; import "element-plus/dist/index.css"; import zhCn from "element-plus/dist/locale/zh-cn.mjs"; // 引入图标 import * as ElementPlusIconsVue from "@element-plus/icons-vue"; // 引入路由 import router from "./routes/index"; // 引入echarts import echarts from "./utils/echarts"; // 引入整个项目入口文件 import App from "./App.vue"; // 定义全局样式 import "./style.less"; // 创建 Store 实例 const piniaStore = createPinia(); // 创建Vue实例 const app = createApp(App); // 注册 Element-plus图标 for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component); } /***********************echart 挂载 START*******************************/ // echarts 挂载到 Vue实例中 // 注意:app.config.globalProperties 和 app.provide('$echarts', echarts) 二选一即可 // Vue.prototype.$echarts = echarts; // vue2的挂载方式 app.config.globalProperties.$echarts = echarts; // vue3的挂载方式(一个用于注册能够被应用内所有组件实例访问到的全局属性的对象。) app.provide('$echarts', echarts); // vue3采用provide, inject方式使用 /***********************echart 挂载 END*******************************/ // 挂载element-plus,使用国际化,设置图标尺寸,及弹框层级 app.use(router).use(piniaStore).use(ElementPlus, { // size: 'small', zIndex: 3000, locale: zhCn, }); // vue挂载到根节点 app.mount("#app"); 组件内使用echarts

前面基本都还简单,但是到了使用的时候,很多人就不知道怎么处理了,以前在 Vue2 的时候还可以通过vue实例 拿到 this 去使用,但是到了 Vue3 里面,没有this 了,怎么办?

不着急,办法还是有的,并且还不止一种,请接着往下看。

通过 getCurrentInstance() 获取组件实例,类似 Vue2 中的 this import { ref, getCurrentInstance } from 'vue'; // 获取echart挂载的DOM节点 const container = ref(); // 获取当前组件实例 const { proxy }: any = getCurrentInstance(); // echarts初始化 let myChart = proxy.$echarts.init(container.value); const option = { // 自定义echarts图标相关配置 }; myChart.setOption(option); // 根据页面大小自动响应图表大小 window.addEventListener("resize", function () { myChart.resize(); }); 通过采用provide, inject方式使用 import { ref, inject} from 'vue'; // 获取echart挂载的DOM节点 const container = ref(); // 通过 inject 接收Echarts const Echarts = inject('$echarts'); // echarts初始化 const myChart = (Echarts as any).init(container.value); const option = { // 自定义echarts图标相关配置 }; myChart.setOption(option); // 根据页面大小自动响应图表大小 window.addEventListener("resize", function () { myChart.resize(); });

上面的两种方式唯一不同的就是如何获取(接收)注册echarts。

到这里就结束了吗?

问题解决

太天真了!

这里我就要问下,上面两种方式的代码能够跑起来吗?

事实上,不行,因为上面 script 内的代码运行的时候,还没有挂载到组件实例上,找不到定义的 ref 对象 container,即使通过document.getElementById('echarts1') 的方式获取DOM节点 一样报 null 或者 undefined。

子任就会出现如下报错:Uncaught (in promise) Error: Initialize failed: invalid dom.

在这里插入图片描述

不信? 那么就控制台打印输出看看两种方式获取的DOM到底是个啥。

import { ref } from 'vue'; // 获取echart挂载的DOM节点 const container = ref(); console.log('获取的DOM-div:', document.getElementById('echarts1'), container.value);

上面的代码输出一下结果:

在这里插入图片描述

那么解决办法也很简单,直接开启一个延时器 setTimeout 就好了。

最后完整代码如下:

import { ref, inject, onBeforeUnmount} from 'vue'; // 获取echart挂载的DOM节点 const container = ref(); // 定义延时器指针对象,便于组件实例销毁的时候以便清除 const timer = ref(); // 通过 inject 接收Echarts const Echarts = inject('$echarts'); // 或 // 通过Vue全局注册方式获取 // const {proxy}: any = getCurrentInstance(); const initEchartsOneFn = () => { // echarts初始化 const myChart = (Echarts as any).init(container.value); // 或 // let myChart = proxy.$echarts.init(container.value); const option = { // 自定义echarts图标相关配置 }; myChart.setOption(option); // 根据页面大小自动响应图表大小 window.addEventListener("resize", function () { myChart.resize(); }); } // 判断定时器是否存在 if (timer.value) { clearTimeout(timer.value); } // 绑定定时器,销毁的时候再次清除 timer.value = setTimeout(() => initEchartsOneFn(), 1000); // 组件实例销毁前清除延时器对象 onBeforeUnmount(() => { if (timer.value) clearTimeout(timer.value); }); // 此处部分将就着看看

上效果图:

在这里插入图片描述

思考 上面解决的方式真的就很好吗?真的就解决了问题吗,有没有一些其他的潜在问题呢?真的就符合Vue3的一些规范了吗?

话不多说,直接上代码看效果。

import { ref, inject, onMounted, onBeforeUnmount} from 'vue'; // 获取echart挂载的DOM节点 const container = ref(); // 定义延时器指针对象,便于组件实例销毁的时候以便清除 const timer = ref(); // 通过 inject 接收Echarts const Echarts = inject('$echarts'); // 或 // 通过Vue全局注册方式获取 // const {proxy}: any = getCurrentInstance(); const initEchartsOneFn = () => { // echarts初始化 const myChart = (Echarts as any).init(container.value); // 或 // let myChart = proxy.$echarts.init(container.value); const option = { // 自定义echarts图标相关配置 }; myChart.setOption(option); // 根据页面大小自动响应图表大小 window.addEventListener("resize", function () { myChart.resize(); }); } /* // 判断定时器是否存在 if (timer.value) { clearTimeout(timer.value); } // 绑定定时器,销毁的时候再次清除 timer.value = setTimeout(() => initEchartsOneFn(), 1000); // 组件实例销毁前清除延时器对象 onBeforeUnmount(() => { if (timer.value) clearTimeout(timer.value); }); */ // 《《上面注释的部分是需要注意的》》 // 其实合理的方式应该是这样子 onMounted(()=>{ initEchartsOneFn() }); // 上面的代码是不是看着更简单直观了呢 // 此处部分将就着看看

以证清白,上图说话:

在这里插入图片描述

最后

非常感谢各位朋友的鼎力支持。

如果这篇文章对你有所帮助,请咚咚大家的 发财黄金手指 ,点赞,收藏。

如果文章有描述错误或者有更好解决方案,也请大家多多 评论。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3