发布时间:2022-11-19 文章分类:WEB开发 投稿人:樱花 字号: 默认 | | 超大 打印

vue3+ts+echarts实现按需引入和类型界定

一直想系统学习一下echarts,无奈今天在引入上就犯了难,现记录一下我的解决方案

为了减少体积和使用的便利,我想实现一个按需和全局的引入

本来是想在main.ts当中直接import * as echarts from 'echarts',然后把这个echarts挂载在app的实例上,但是以我现有的经验,这可能要涉及到this的问题,vue3已经极力避免this的出现,所以在看了相关大神的文章之后,我决定在App.vue的界面进行引入,然后利用provide函数,将形成的echarts变量传递给其他的子页面,这样就能实现全局使用的问题

//App.vue
import{provide} from 'vue'
import * as echarts from 'echarts'
provide("echarts",echarts)
//其他子页面中
import {inject} from 'vue'
let echarts=inject<any>("echarts")

第二个问题是关于按需的问题,这里我直接贴上官方的写法,简单看看就行

import * as echarts from 'echarts/core';
import {
BarChart,
// 系列类型的定义后缀都为 SeriesOption
BarSeriesOption,
LineChart,
LineSeriesOption
} from 'echarts/charts';
import {
TitleComponent,
// 组件类型的定义后缀都为 ComponentOption
TitleComponentOption,
TooltipComponent,
TooltipComponentOption,
GridComponent,
GridComponentOption,
// 数据集组件
DatasetComponent,
DatasetComponentOption,
// 内置数据转换器组件 (filter, sort)
TransformComponent
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = echarts.ComposeOption<
| BarSeriesOption
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>;
// 注册必须的组件
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
]);
const option: ECOption = {
// ...
};

以上很明显引入了一些bar图和line图,并且引入以option为结尾的组件类型,此外还引入了一些title基础组件和对应类型,并利用use的方法将其与核心的echarts对象进行整合,还规制了一个ECOption作为echarts配置对象的类型,这确实实现了按需引入,但是问题是按照我上面的写法,provide不能传递type,所以我需要将类型和echarts分开写到两个文件里。

首先看一下App.vue的文件中我是怎么按需配置echarts的

//App.vue文件
// 我本来想在这里引入echart
import { provide } from 'vue';
import * as echarts from 'echarts/core';
import {
BarChart,
// 系列类型的定义后缀都为 SeriesOption
LineChart
} from 'echarts/charts';
import {
TitleComponent,
// 组件类型的定义后缀都为 ComponentOption
TooltipComponent,
GridComponent,
// 数据集组件
DatasetComponent,
// 内置数据转换器组件 (filter, sort)
TransformComponent
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
// 注册必须的组件
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
BarChart,
LineChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
]);
// 把这个配置好的echartprovide出去
provide("echarts", echarts)
// 把这个option的选项类型也provide出去,但是provide方法无法使用传递类型,那我这边只能放弃

其实就是把全部的类型都摘了出来,然后单独写到一个echart.d.ts的申明文件中去,以下是代码

//echart.d.ts
// 因为provide不能传递type的原因,我们将echart的option类型单独抽取出来写一个申明文件
// 1.我们引入了线图和bar图,所以这里我们引入了两者的类型
import { ComposeOption } from 'echarts/core';
import {
BarSeriesOption,
LineSeriesOption
} from 'echarts/charts';
//2.引入组件,也就是option选项中的类型
import {
// 组件类型的定义后缀都为 ComponentOption
TitleComponentOption,
TooltipComponentOption,
GridComponentOption,
// 数据集组件
DatasetComponentOption,
} from 'echarts/components';
// 3.通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = ComposeOption<
| BarSeriesOption
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>;
// 4.将这个类型暴露出去
export { ECOption }

然后是具体使用的代码

import { inject, onMounted } from 'vue';
// 引入我自定义的图像option类型
import { ECOption } from '../echart'
let echarts = inject<any>("echarts")
// 将echart的创建,压缩成一个方程
let echartInit = () => {
// 将option选项抽离出来
let option: ECOption = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
}
// echart图标的绘制
var myChart = echarts.init(document.getElementById('chart'));
myChart.setOption(option);
}
onMounted(() => {
echartInit()
})

就是我的解决方案

vue3按需引入echarts问题及使用

vue3+ts+echarts实现按需引入和类型界定方式

参考官方示例:Examples - Apache ECharts

1、安装

npm install echarts --save

如果要使用3d类型的需要引入 echarts-gl(本文需要)

npm install echarts-gl --save

2、main.js

// 引入 echarts 核心模块
import * as echarts from 'echarts/core';
// 引入 echarts-gl 模块
import { GlobeComponent } from 'echarts-gl/components';
 
// 引入 Canvas 渲染器
import { CanvasRenderer } from 'echarts/renderers';
 
// 注册必须的组件
echarts.use([GlobeComponent, CanvasRenderer]);
app.config.globalProperties.$echarts = echarts; // 注意这行要在 const app = createApp(App) 之后

3、使用

<template>
<div class="earth" ref="earth">
<div id="main" ref="earthMain"></div>
</div>
</template>
<script>
import { defineComponent, ref, onMounted, getCurrentInstance } from "vue";
import earthImg from "@/assets/img/earth.jpg"
export default defineComponent({
name: "frontPage",
components: {},
setup() {
const { proxy } = getCurrentInstance(); // !!!!
let echarts = proxy.$echarts;
let earth = ref(null);
let earthMain = ref(null);
let earthChart;
onMounted(() => {
let height = earth.value.offsetWidth * 0.0625;
earth.value.style.height = height + "rem";
initEarth();
});
window.addEventListener("resize", function(){
let height = earth.value.offsetWidth;
height *= 0.0625;
earth.value.style.height = height + "rem";
if(earthChart){
earthChart.resize();
}
})
let initEarth = function(){
earthChart = echarts.init(earthMain.value);
let option = {
globe: {
baseTexture: earthImg,
displacementScale: 0.1,
shading: 'realistic',
light: {
ambient: {
intensity: 0.9
},
main: {
intensity: 0.1
}
},
viewControl: {
autoRotate: true,
autoRotateAfterStill: 0.1,
// 0 不缩放
zoomSensitivity: 0
},
top: 0,
left: 0,
right: 0,
bottom: 0
},
series: []
};
option && earthChart.setOption(option);
}
return {
earth,
earthMain
}
},
});
</script>
<style lang="scss" scoped>
.earth {
max-height: 600px;
>div{
width: 100%;
height: 100%;
max-width: 600px;
max-height: 600px;
}
}
</style>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持本站。