Vue3 组合式 全局挂载
# vue 2
# vue 3
vue 3 官方极力避免 this 的产生
echarts ts 按需引入官方文档:在项目中引入 ECharts - 入门篇 - Handbook - Apache ECharts (opens new window)
# provide / inject(推荐)
# 具体使用
我们可以在 main.js 或是 App.vue 中 provide 函数传递变量
例如在 main.js 中
import { createApp } from 'vue'
import App from './App.vue'
import * as echarts from 'echarts';
let app = createApp(App);
// 全局挂载
app.provide('$echarts',echarts);
app.mount('#app')
2
3
4
5
6
7
8
9
App.vue
import{provide} from 'vue'
import * as echarts from 'echarts'
provide("$echarts",echarts)
2
3
子组件使用
<script setup>
import { inject, onMounted } from "vue";
// 导入挂载
const echarts = inject<any>("$echarts");
onMounted(() => {
let myChart = echarts.init(document.getElementById('main'));
console.log(myChart);
});
</script>
2
3
4
5
6
7
8
9
10
11
# 按需导入
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 = {
// ...
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
以上很明显引入了一些 bar 图和 line 图,并且引入以 option 为结尾的组件类型,此外还引入了一些 title 基础组件和对应类型,并利用 use 的方法将其与核心的 echarts 对象进行整合,还规制了一个 ECOption 作为 echarts 配置对象的类型,这确实实现了按需引入,但是问题是按照上面的写法,provide 不能传递 type,所以我需要将类型和 echarts 分开写到两个文件里
所以方法是首先单独导出 echarts 对象
import * as echarts from 'echarts/core';
import {
BarChart,
LineChart
} from 'echarts/charts';
import {
TitleComponent,
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
]);
export default echarts
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
我个人是配置在 src/plugins/echarts/index.ts
,最后在 main.ts
导入,然后全局挂载即可
最后关键就是配置类型声明文件 echarts.d.ts
import type {
// 系列类型的定义后缀都为 SeriesOption
BarSeriesOption,
LineSeriesOption
} from 'echarts/charts';
import type {
// 组件类型的定义后缀都为 ComponentOption
TitleComponentOption,
TooltipComponentOption,
GridComponentOption,
DatasetComponentOption
} from 'echarts/components';
import type {
ComposeOption,
} from 'echarts/core';
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = ComposeOption<
| BarSeriesOption
| LineSeriesOption
| TitleComponentOption
| TooltipComponentOption
| GridComponentOption
| DatasetComponentOption
>;
export { ECOption }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
然后就是代码中具体使用
import { inject, onMounted } from 'vue';
import { ECOption } from '../echart'
let echarts = inject<any>("$echarts")
let echartInit = () => {
let option: ECOption = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
}
var myChart = echarts.init(document.getElementById('chart'));
myChart.setOption(option);
}
onMounted(() => {
echartInit()
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# globalProperties
# JS
注:本方法实测失败
//vue3 main.js文件
import { createApp } from 'vue'
import App from './App.vue'
import * as echarts from 'echarts';
let app = createApp(App);
//全局挂载echarts属性
app.config.globalProperties.$echarts = echarts;
app.mount('#app')
2
3
4
5
6
7
8
9
子组件调用
<script setup>
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance();
//调用
proxy.echarts
</script>
2
3
4
5
6
# TS
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// vue3全局变量挂载
app.config.globalProperties.$http = http
const demo = 'demo'
app.config.globalProperties.$demo = demo
app.mount('#app')
2
3
4
5
6
7
8
9
10
11
子组件使用
如果是选项式
<template>
<div>
{{ $demo }}
</div>
</template>
<script lang="ts">
export default {
mounted() {
console.log(this.$demo)
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
组合式之中因为没有 this ,我们需要导入获取当前实例的方法,解构到 proxy 来使用
方法一:获取全局属性的所有属性
<script lang="ts" setup>
import { reactive, ref, getCurrentInstance } from 'vue'
// 引入vue组件内部实例类型用于引入全局变量的类型断言
import type { ComponentInternalInstance } from 'vue'
const currentInstance = C()
const globalProperties = currentInstance?.appContext.config.globalProperties
console.log(globalProperties);
</script>
2
3
4
5
6
7
8
9
10
11
方法二:解构出代理 proxy ,之后 getCurrentInstance () 的 ts 类型检测是 ComponentInternalInstance | null
,然后再进行类型检测
<script setup lang="ts">
import { ContentWrap } from '@/components/ContentWrap'
import { useI18n } from '@/hooks/web/useI18n'
import { getCurrentInstance } from 'vue'
defineOptions({
name: 'Menu111'
})
const { t } = useI18n()
const { proxy } = getCurrentInstance() as ComponentInternalInstance
console.log(proxy.$echarts)
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
但是上面语句会出现无法识别 $echarts 类型,可以按照上面方法配置类型声明文件
# 补充
# 类型断言
类型断言(Type Assertion)可以用来手动指定一个值的类型
值 as 类型
或
<类型>值
在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即 值 as 类型
。
形如 <Foo>
的语法在 tsx 中表示的是一个 ReactNode
,在 ts 中除了表示类型断言之外,也可能是表示一个泛型 (opens new window)。
故建议大家在使用类型断言时,统一使用 值 as 类型
这样的语法