Vue3自定義Echars組件附帶全局配置方式
更新時間:2024年03月11日 09:15:58 作者:Circle_Key
這篇文章主要介紹了Vue3自定義Echars組件附帶全局配置方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
Vue3自定義Echars組件附帶全局配置
<template>
<div ref="chart" :id="id" :class="className" :style="{ height: height, width: width }"></div>
</template>
<script setup>
import { ref, reactive, toRefs, onMounted, onBeforeUnmount,watch } from 'vue'
import * as echarts from 'echarts';
// 傳遞參數(shù)
const props = defineProps({
className: {
type: String,
default: 'chart'
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '280px'
},
options: {
type: Object,
default: () => { }
}
})
const chart = ref(null);
const createChart = () => {
const myChart = echarts.init(chart.value);
chart.value = echarts.init(chart.value, 'tdTheme')
myChart.setOption(props.options,true);
// chart.value.setOption(props.options, true)
window.addEventListener("resize", () => {
chart.value.resize()
})
};
watch(() => props.options, (options) => {
if (chart.value) {
// 設(shè)置true清空echart緩存
chart.value.setOption(options, true)
}
}, { deep: true })
onMounted(() => {
createChart();
});
onBeforeUnmount(() => {
window.removeEventListener("resize", () => {
chart.value.resize()
})
chart.value.dispose()
chart.value = null
})
</script>import Echart from './components/echart/index.vue'
import echarts from 'echarts'
const app = createApp(App)
// 將echarts掛載到全局對象上
app.config.globalProperties.$echarts = echarts
// 注冊全局組件
app.component('Echart', Echart)案列
<template>
<div ref="chart" style="width: 600px; height: 400px;"></div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';
const chart = ref(null);
const createChart = () => {
const myChart = echarts.init(chart.value);
myChart.setOption({
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}]
});
};
onMounted(() => {
createChart();
});
</script>vue3封裝echarts組件
在開發(fā)項(xiàng)目過程中需要封裝echarts組件,方便多次使用,以下是封裝的詳細(xì)過程。
前置動作:安裝echarts以及resize-observer-polyfill插件
- 新建echarts.ts文件
import * as echarts from "echarts/core";
/**
* 這里按需引入使用到的圖表類型
*/
import { BarChart, LineChart, type LineSeriesOption, PieChart, type PieSeriesOption } from "echarts/charts";
/**
* 這里按需引入使用到的配置
* 特別地 包括MarkPoint markLine等這些也要單獨(dú)使用 不然在圖表中無法顯示
*/
import {
LegendComponent,
type LegendComponentOption,
TitleComponent,
// 組件類型的定義后綴都為 ComponentOption
type TitleComponentOption,
TooltipComponent,
type TooltipComponentOption,
GridComponent,
type GridComponentOption,
DataZoomComponent,
type DataZoomComponentOption,
// 數(shù)據(jù)集組件
DatasetComponent,
type DatasetComponentOption,
// 標(biāo)記組件
MarkAreaComponent,
type MarkAreaComponentOption,
MarkLineComponent,
type MarkLineComponentOption,
MarkPointComponent,
type MarkPointComponentOption,
// 內(nèi)置數(shù)據(jù)轉(zhuǎn)換器組件 (filter, sort)
TransformComponent,
} from "echarts/components";
import { LabelLayout, UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
import { ref, shallowRef, onMounted, onBeforeUnmount } from "vue";
import ResizeObserver from "resize-observer-polyfill";
import throttle from "lodash/throttle";
/**
* 引入的配置通過 ComposeOption 來組合出一個只有必須組件和圖表的 Option 類型
*/
export type ECOption = echarts.ComposeOption<
| LineSeriesOption
| PieSeriesOption
| LegendComponentOption
| TitleComponentOption
| TooltipComponentOption
| DataZoomComponentOption
| GridComponentOption
| DatasetComponentOption
| MarkAreaComponentOption
| MarkLineComponentOption
| MarkPointComponentOption
>;
/**
* 注冊按需引入的組件
*/
echarts.use([
LegendComponent,
TitleComponent,
TooltipComponent,
GridComponent,
DataZoomComponent,
DatasetComponent,
MarkAreaComponent,
MarkLineComponent,
MarkPointComponent,
TransformComponent,
BarChart,
LineChart,
PieChart,
LabelLayout,
UniversalTransition,
CanvasRenderer,
]);
export default function useChart() {
const canvasEl = shallowRef();
const myChart = shallowRef();
/**
* 監(jiān)聽容器寬度變化或者瀏覽器窗口變化對echarts圖表進(jìn)行自動展示
* 不用window.addEventListener("resize", resizeFn)的原因是這個方法只是監(jiān)聽瀏覽器窗口的不變化
* -對所在容器的大小變化不進(jìn)行監(jiān)聽 很難滿足開發(fā)場景的需求
*/
const resizeObserver = ref<ResizeObserver>();
const bindResize = () => {
const deboundResize = throttle(() => {
myChart.value?.resize();
}, 500);
resizeObserver.value = new ResizeObserver(() => {
deboundResize();
// myChart.value?.resize();
});
resizeObserver.value.observe(canvasEl.value);
};
// 解綁 resize
const unbindResize = () => {
resizeObserver.value?.unobserve(canvasEl.value);
};
onMounted(() => {
/**
* 注冊echarts并開啟監(jiān)聽容器大小變化
*/
myChart.value = echarts.init(canvasEl.value);
bindResize();
});
onBeforeUnmount(() => {
/**
* 銷毀監(jiān)聽和echarts
*/
unbindResize();
myChart.value?.dispose();
myChart.value = null;
});
return {
myChart,
canvasEl,
};
}
- 頁面封裝
<template>
<div>
<div class="chart-container" :style="containerStyle">
<div v-show="dataEmptyFlag" class="chart-empty">
<span class="empty-title">暫無數(shù)據(jù)</span>
</div>
<div ref="canvasEl" :style="containerStyle" />
<div v-show="loading" class="chart-loading"><Spin /></div>
</div>
</div>
</template>
<script setup lang="ts">
import { Spin } from "ant-design-vue";
import { ref, watch } from "vue";
import useChart from "./useECharts";
import type { ECOption } from "./useECharts";
interface ChartProps {
containerStyle?: any;
loading?: boolean;
dataEmptyFlag?: boolean;
options?: ECOption;
}
const props = withDefaults(defineProps<ChartProps>(), {
containerStyle: {
height: "990px",
width: "100%",
},
loading: false,
dataEmptyFlag: false,
});
const { myChart, canvasEl } = useChart();
watch(
() => props?.options,
(cur) => {
if (myChart) {
/**
* 這里繪制圖表前先清空上一次數(shù)據(jù) 否則有時候會出現(xiàn)數(shù)據(jù)殘余的情況
*/
myChart.value.clear();
myChart.value.setOption(cur);
}
},
);
</script>
<style scoped>
.chart-container {
position: relative;
width: 100%;
}
.chart-loading {
align-items: center;
background-color: #ffffff;
bottom: 0;
display: flex;
justify-content: center;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: 1999;
}
.chart-empty {
position: absolute;
z-index: 1;
left: 0;
right: 0;
top: 0;
bottom: 0;
color: #888;
font-size: 14px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.empty-title {
font-size: 16px;
font-weight: 500;
color: #000;
}
</style>
- 組件調(diào)用
/** * 參入對應(yīng)的參數(shù)以及圖表配置項(xiàng) */ <anewCharts :loading="loading" :data-empty-flag="dataEmptyFlag" :containerStyle="chartStyle" :options="chartOptions"></anewCharts>
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:
相關(guān)文章
Vue3使用postcss-px-to-viewport實(shí)現(xiàn)頁面自適應(yīng)
postcss-px-to-viewport 是一個 PostCSS 插件,它可以將 px 單位轉(zhuǎn)換為視口單位,下面我們就看看如何使用postcss-px-to-viewport實(shí)現(xiàn)頁面自適應(yīng)吧2024-01-01
vue項(xiàng)目中的public、static及指定不編譯文件問題
這篇文章主要介紹了vue項(xiàng)目中的public、static及指定不編譯文件問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決
這篇文章主要介紹了vue子組件封裝彈框只能執(zhí)行一次的mounted問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
vue3中使用scss加上scoped導(dǎo)致樣式失效問題
這篇文章主要介紹了vue3中使用scss加上scoped導(dǎo)致樣式失效問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10

