mirror of
https://github.com/ecomfe/vue-echarts.git
synced 2025-10-28 03:25:02 +08:00
refactor: rename options to option to align with ECharts itself
- removed built-in styles - use ECharts' built-in throttle - generate bundled .d.ts, hack three methods for now - loadingOptions can be any object type
This commit is contained in:
@ -11,9 +11,9 @@ import {
|
||||
onUnmounted,
|
||||
h,
|
||||
PropType
|
||||
} from "vue";
|
||||
} from "vue-demi";
|
||||
import { init as initChart } from "echarts/core";
|
||||
import { EChartsType, OptionType } from "@/types";
|
||||
import { EChartsType, OptionType } from "./types";
|
||||
import {
|
||||
usePublicAPI,
|
||||
useAutoresize,
|
||||
@ -21,7 +21,6 @@ import {
|
||||
useLoading,
|
||||
loadingProps
|
||||
} from "./composables";
|
||||
import "./style.css";
|
||||
|
||||
type InitParameters = Parameters<typeof initChart>;
|
||||
type ThemeParameter = InitParameters[1];
|
||||
@ -30,7 +29,7 @@ type InitOptsParameter = InitParameters[2];
|
||||
export default defineComponent({
|
||||
name: "echarts",
|
||||
props: {
|
||||
options: Object as PropType<OptionType>,
|
||||
option: Object as PropType<OptionType>,
|
||||
theme: {
|
||||
type: [Object, String] as PropType<ThemeParameter>
|
||||
},
|
||||
@ -47,12 +46,12 @@ export default defineComponent({
|
||||
) as InitOptsParameter;
|
||||
const root = ref<HTMLElement>();
|
||||
const chart = shallowRef<EChartsType>();
|
||||
const manualOptions = shallowRef<OptionType>();
|
||||
const realOptions = computed(
|
||||
() => manualOptions.value || props.options || Object.create(null)
|
||||
const manualOption = shallowRef<OptionType>();
|
||||
const realOption = computed(
|
||||
() => manualOption.value || props.option || Object.create(null)
|
||||
);
|
||||
|
||||
function init(options?: OptionType) {
|
||||
function init(option?: OptionType) {
|
||||
if (chart.value || !root.value) {
|
||||
return;
|
||||
}
|
||||
@ -83,18 +82,18 @@ export default defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
instance.setOption(options || realOptions.value, true);
|
||||
instance.setOption(option || realOption.value, true);
|
||||
}
|
||||
|
||||
function mergeOptions(options: OptionType, ...rest: any[]) {
|
||||
function setOption(option: OptionType, ...rest: any[]) {
|
||||
if (props.manualUpdate) {
|
||||
manualOptions.value = options;
|
||||
manualOption.value = option;
|
||||
}
|
||||
|
||||
if (!chart.value) {
|
||||
init(options);
|
||||
init(option);
|
||||
} else {
|
||||
chart.value.setOption(options, ...rest);
|
||||
chart.value.setOption(option, ...rest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,18 +113,18 @@ export default defineComponent({
|
||||
loading,
|
||||
loadingOptions
|
||||
} = toRefs(props);
|
||||
let unwatchOptions: (() => void) | null = null;
|
||||
let unwatchOption: (() => void) | null = null;
|
||||
watch(
|
||||
manualUpdate,
|
||||
manualUpdate => {
|
||||
if (typeof unwatchOptions === "function") {
|
||||
unwatchOptions();
|
||||
unwatchOptions = null;
|
||||
if (typeof unwatchOption === "function") {
|
||||
unwatchOption();
|
||||
unwatchOption = null;
|
||||
}
|
||||
|
||||
if (!manualUpdate) {
|
||||
unwatchOptions = watch(
|
||||
() => props.options,
|
||||
unwatchOption = watch(
|
||||
() => props.option,
|
||||
(val, oldVal) => {
|
||||
if (!val) {
|
||||
return;
|
||||
@ -133,12 +132,12 @@ export default defineComponent({
|
||||
if (!chart.value) {
|
||||
init();
|
||||
} else {
|
||||
// mutating `options` will lead to merging
|
||||
// mutating `option` will lead to merging
|
||||
// replacing it with new reference will lead to not merging
|
||||
// eg.
|
||||
// `this.options = Object.assign({}, this.options, { ... })`
|
||||
// `this.option = Object.assign({}, this.option, { ... })`
|
||||
// will trigger `this.chart.setOption(val, true)
|
||||
// `this.options.title.text = 'Trends'`
|
||||
// `this.option.title.text = 'Trends'`
|
||||
// will trigger `this.chart.setOption(val, false)`
|
||||
chart.value.setOption(val, val !== oldVal);
|
||||
}
|
||||
@ -170,10 +169,10 @@ export default defineComponent({
|
||||
|
||||
useLoading(chart, loading, loadingOptions);
|
||||
|
||||
useAutoresize(chart, autoresize, root, realOptions);
|
||||
useAutoresize(chart, autoresize, root, realOption);
|
||||
|
||||
onMounted(() => {
|
||||
if (props.options) {
|
||||
if (props.option) {
|
||||
init();
|
||||
}
|
||||
});
|
||||
@ -182,7 +181,7 @@ export default defineComponent({
|
||||
|
||||
return {
|
||||
root,
|
||||
mergeOptions,
|
||||
setOption,
|
||||
...publicApi
|
||||
};
|
||||
},
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Ref } from "vue";
|
||||
import { EChartsType, OptionType } from "@/types";
|
||||
import { Ref } from "vue-demi";
|
||||
import { EChartsType, OptionType } from "../types";
|
||||
|
||||
const METHOD_NAMES = [
|
||||
"getWidth",
|
||||
"getHeight",
|
||||
"getDom",
|
||||
"getOption",
|
||||
"resize",
|
||||
"dispatchAction",
|
||||
@ -24,7 +23,7 @@ type PublicMethods = Pick<EChartsType, MethodName>;
|
||||
|
||||
export function usePublicAPI(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
init: (options?: OptionType) => void
|
||||
init: (option?: OptionType) => void
|
||||
) {
|
||||
function makePublicMethod<T extends MethodName>(
|
||||
name: T
|
||||
@ -41,6 +40,12 @@ export function usePublicAPI(
|
||||
};
|
||||
}
|
||||
|
||||
function makeAnyMethod<T extends MethodName>(
|
||||
name: T
|
||||
): (...args: any[]) => ReturnType<EChartsType[T]> {
|
||||
return makePublicMethod(name) as any;
|
||||
}
|
||||
|
||||
function makePublicMethods(): PublicMethods {
|
||||
const methods = Object.create(null);
|
||||
METHOD_NAMES.forEach(name => {
|
||||
@ -50,5 +55,10 @@ export function usePublicAPI(
|
||||
return methods as PublicMethods;
|
||||
}
|
||||
|
||||
return makePublicMethods();
|
||||
return {
|
||||
...makePublicMethods(),
|
||||
dispatchAction: makeAnyMethod("dispatchAction"),
|
||||
getDataURL: makeAnyMethod("getDataURL"),
|
||||
getConnectedDataURL: makeAnyMethod("getConnectedDataURL")
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { Ref, watch } from "vue";
|
||||
import { Ref, watch } from "vue-demi";
|
||||
import { throttle } from "echarts/core";
|
||||
import { addListener, removeListener, ResizeCallback } from "resize-detector";
|
||||
import { EChartsType, OptionsType } from "@/types";
|
||||
import { EChartsType, OptionType } from "../types";
|
||||
|
||||
export function useAutoresize(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
autoresize: Ref<boolean>,
|
||||
root: Ref<HTMLElement | undefined>,
|
||||
options: Ref<OptionsType>
|
||||
option: Ref<OptionType>
|
||||
): void {
|
||||
let resizeListener: ResizeCallback | null = null;
|
||||
let lastArea = 0;
|
||||
@ -22,16 +23,16 @@ export function useAutoresize(
|
||||
watch([root, chart, autoresize], ([root, chart, autoresize], _, cleanup) => {
|
||||
if (root && chart && autoresize) {
|
||||
lastArea = getArea();
|
||||
resizeListener = () => {
|
||||
resizeListener = throttle(() => {
|
||||
if (lastArea === 0) {
|
||||
chart.setOption(Object.create(null), true);
|
||||
chart.resize();
|
||||
chart.setOption(options.value, true);
|
||||
chart.setOption(option.value, true);
|
||||
} else {
|
||||
chart.resize();
|
||||
}
|
||||
lastArea = getArea();
|
||||
};
|
||||
}, 100);
|
||||
|
||||
addListener(root, resizeListener);
|
||||
}
|
||||
|
||||
@ -1,25 +1,10 @@
|
||||
import { Ref, PropType, watchEffect } from "vue";
|
||||
import { EChartsType } from "@/types";
|
||||
|
||||
export interface LoadingOptions {
|
||||
text?: string;
|
||||
color?: string;
|
||||
textColor?: string;
|
||||
maskColor?: string;
|
||||
zlevel?: number;
|
||||
fontSize?: number;
|
||||
showSpinner?: boolean;
|
||||
spinnerRadius?: number;
|
||||
lineWidth?: number;
|
||||
fontWeight?: string | number;
|
||||
fontStyle?: string;
|
||||
fontFamily?: string;
|
||||
}
|
||||
import { Ref, watchEffect } from "vue-demi";
|
||||
import { EChartsType } from "../types";
|
||||
|
||||
export function useLoading(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
loading: Ref<boolean>,
|
||||
loadingOptions?: Ref<LoadingOptions | undefined>
|
||||
loadingOptions?: Ref<object | undefined>
|
||||
): void {
|
||||
watchEffect(() => {
|
||||
const instance = chart.value;
|
||||
@ -37,5 +22,5 @@ export function useLoading(
|
||||
|
||||
export const loadingProps = {
|
||||
loading: Boolean,
|
||||
loadingOptions: Object as PropType<LoadingOptions>
|
||||
loadingOptions: Object
|
||||
};
|
||||
|
||||
@ -11,14 +11,14 @@
|
||||
<button @click="mutate" :disabled="useRef">Mutate data</button>
|
||||
<button @click="set" :disabled="!useRef">Set data</button>
|
||||
<button @click="mutateLoadingOptions" :disabled="!loading">
|
||||
Mutate loading options
|
||||
Mutate loading option
|
||||
</button>
|
||||
</div>
|
||||
<v-chart
|
||||
style="width: 100%; height: 400px"
|
||||
ref="foo"
|
||||
:autoresize="autoresize"
|
||||
:options="realOptions"
|
||||
:option="realOption"
|
||||
:loading="loading"
|
||||
:loading-options="loadingOptions"
|
||||
:theme="defaultTheme ? null : 'dark'"
|
||||
@ -36,49 +36,48 @@ import * as echarts from "echarts/core";
|
||||
import { GridComponent } from "echarts/components";
|
||||
import { LineChart } from "echarts/charts";
|
||||
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
|
||||
|
||||
echarts.use([GridComponent, LineChart, CanvasRenderer, SVGRenderer]);
|
||||
|
||||
export default defineComponent({
|
||||
name: "App",
|
||||
components: {
|
||||
VChart
|
||||
VChart,
|
||||
},
|
||||
setup() {
|
||||
const foo = ref();
|
||||
const options = reactive({
|
||||
const option = reactive({
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value"
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [150, 230, 224, 218, 135, 147, 260],
|
||||
type: "line"
|
||||
}
|
||||
]
|
||||
type: "line",
|
||||
},
|
||||
],
|
||||
});
|
||||
const optionsRef = ref({
|
||||
const optionRef = ref({
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value"
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: [233, 128, 184, 302, 208, 287, 212],
|
||||
type: "line"
|
||||
}
|
||||
]
|
||||
type: "line",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const loadingOptions = reactive({
|
||||
text: "正在加载..."
|
||||
text: "正在加载...",
|
||||
});
|
||||
|
||||
const autoresize = ref<boolean>(true);
|
||||
@ -87,26 +86,26 @@ export default defineComponent({
|
||||
const useRef = ref<boolean>(false);
|
||||
const loading = ref<boolean>(false);
|
||||
const initOptions = computed(() => ({
|
||||
renderer: useSvg.value ? "svg" : "canvas"
|
||||
renderer: useSvg.value ? "svg" : "canvas",
|
||||
}));
|
||||
const realOptions = computed(() =>
|
||||
useRef.value ? optionsRef.value : options
|
||||
const realOption = computed(() =>
|
||||
useRef.value ? optionRef.value : option
|
||||
);
|
||||
|
||||
function mutate() {
|
||||
options.series[0].data = [150, 230, 224, 218, 135, 147, 260].map(
|
||||
val => val + Math.round(50 * Math.random())
|
||||
option.series[0].data = [150, 230, 224, 218, 135, 147, 260].map(
|
||||
(val) => val + Math.round(50 * Math.random())
|
||||
);
|
||||
}
|
||||
|
||||
function set() {
|
||||
optionsRef.value = {
|
||||
optionRef.value = {
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
},
|
||||
yAxis: {
|
||||
type: "value"
|
||||
type: "value",
|
||||
},
|
||||
series: [
|
||||
{
|
||||
@ -117,11 +116,11 @@ export default defineComponent({
|
||||
302 + Math.round(50 * Math.random()),
|
||||
208 + Math.round(50 * Math.random()),
|
||||
287 + Math.round(50 * Math.random()),
|
||||
212 + Math.round(50 * Math.random())
|
||||
212 + Math.round(50 * Math.random()),
|
||||
],
|
||||
type: "line"
|
||||
}
|
||||
]
|
||||
type: "line",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@ -135,7 +134,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
return {
|
||||
realOptions,
|
||||
realOption,
|
||||
autoresize,
|
||||
defaultTheme,
|
||||
useSvg,
|
||||
@ -147,8 +146,8 @@ export default defineComponent({
|
||||
loadingOptions,
|
||||
mutateLoadingOptions,
|
||||
foo,
|
||||
log
|
||||
log,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
.echarts {
|
||||
width: 400px;
|
||||
height: 300px;
|
||||
}
|
||||
Reference in New Issue
Block a user