mirror of
https://github.com/ecomfe/vue-echarts.git
synced 2025-10-29 16:07:26 +08:00
fix: delay first setOption until initial resize, update deps
This commit is contained in:
@ -3,7 +3,6 @@ import {
|
||||
defineComponent,
|
||||
unref,
|
||||
shallowRef,
|
||||
toRef,
|
||||
toRefs,
|
||||
watch,
|
||||
computed,
|
||||
@ -63,13 +62,8 @@ export default defineComponent({
|
||||
...loadingProps
|
||||
},
|
||||
inheritAttrs: false,
|
||||
created() {
|
||||
console.log(this);
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error listeners for Vue 2 compatibility
|
||||
setup(props, { attrs, listeners }) {
|
||||
type T = Required<typeof props>;
|
||||
const root = shallowRef<HTMLElement>();
|
||||
const chart = shallowRef<EChartsType>();
|
||||
const manualOption = shallowRef<Option>();
|
||||
@ -78,9 +72,13 @@ export default defineComponent({
|
||||
INIT_OPTIONS_KEY,
|
||||
null
|
||||
) as InitOptionsInjection;
|
||||
const defaultUpdateOptions = inject(UPDATE_OPTIONS_KEY, {
|
||||
lazyUpdate: true
|
||||
}) as UpdateOptionsInjection;
|
||||
const defaultUpdateOptions = inject(
|
||||
UPDATE_OPTIONS_KEY,
|
||||
null
|
||||
) as UpdateOptionsInjection;
|
||||
|
||||
const { autoresize, manualUpdate, loading, loadingOptions } = toRefs(props);
|
||||
|
||||
const realOption = computed(
|
||||
() => manualOption.value || props.option || Object.create(null)
|
||||
);
|
||||
@ -91,12 +89,6 @@ export default defineComponent({
|
||||
const realUpdateOptions = computed(
|
||||
() => props.updateOptions || unref(defaultUpdateOptions) || {}
|
||||
);
|
||||
|
||||
const { autoresize, manualUpdate, loading } = toRefs(props);
|
||||
|
||||
const initOptions = toRef(props, "initOptions");
|
||||
const loadingOptions = toRef(props, "loadingOptions");
|
||||
|
||||
const nonEventAttrs = computed(() => omitOn(attrs));
|
||||
|
||||
function init(option?: Option) {
|
||||
@ -142,8 +134,6 @@ export default defineComponent({
|
||||
}
|
||||
});
|
||||
|
||||
instance.setOption(option || realOption.value, realUpdateOptions.value);
|
||||
|
||||
function resize() {
|
||||
if (instance && !instance.isDisposed()) {
|
||||
// temporarily suppress errors caused by https://github.com/apache/echarts/issues/14846
|
||||
@ -159,10 +149,19 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
function commit() {
|
||||
instance.setOption(option || realOption.value, realUpdateOptions.value);
|
||||
}
|
||||
|
||||
if (autoresize.value) {
|
||||
// Try to make chart fit to container in case container size
|
||||
// is changed synchronously or in already queued microtasks
|
||||
nextTick(resize);
|
||||
nextTick(() => {
|
||||
resize();
|
||||
commit();
|
||||
});
|
||||
} else {
|
||||
commit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +216,7 @@ export default defineComponent({
|
||||
);
|
||||
|
||||
watch(
|
||||
[realTheme, initOptions],
|
||||
[realTheme, realInitOptions],
|
||||
() => {
|
||||
cleanup();
|
||||
init();
|
||||
@ -237,7 +236,7 @@ export default defineComponent({
|
||||
|
||||
useLoading(chart, loading, loadingOptions);
|
||||
|
||||
useAutoresize(chart, autoresize, root, realOption);
|
||||
useAutoresize(chart, autoresize, root);
|
||||
|
||||
onMounted(() => {
|
||||
if (props.option) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Ref, unref } from "vue-demi";
|
||||
import { Ref } from "vue-demi";
|
||||
import { EChartsType, Option } from "../types";
|
||||
|
||||
const METHOD_NAMES = [
|
||||
@ -26,7 +26,7 @@ type PublicMethods = Pick<EChartsType, MethodName>;
|
||||
export function usePublicAPI(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
init: (option?: Option) => void
|
||||
) {
|
||||
): PublicMethods {
|
||||
function makePublicMethod<T extends MethodName>(
|
||||
name: T
|
||||
): (...args: Parameters<EChartsType[T]>) => ReturnType<EChartsType[T]> {
|
||||
@ -42,12 +42,6 @@ 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 => {
|
||||
@ -57,10 +51,5 @@ export function usePublicAPI(
|
||||
return methods as PublicMethods;
|
||||
}
|
||||
|
||||
return {
|
||||
...makePublicMethods(),
|
||||
dispatchAction: makeAnyMethod("dispatchAction"),
|
||||
getDataURL: makeAnyMethod("getDataURL"),
|
||||
getConnectedDataURL: makeAnyMethod("getConnectedDataURL")
|
||||
};
|
||||
return makePublicMethods();
|
||||
}
|
||||
|
||||
@ -1,37 +1,19 @@
|
||||
import { Ref, watch } from "vue-demi";
|
||||
import { throttle } from "echarts/core";
|
||||
import { addListener, removeListener, ResizeCallback } from "resize-detector";
|
||||
import { EChartsType, Option } from "../types";
|
||||
import { EChartsType } from "../types";
|
||||
|
||||
export function useAutoresize(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
autoresize: Ref<boolean>,
|
||||
root: Ref<HTMLElement | undefined>,
|
||||
option: Ref<Option>
|
||||
root: Ref<HTMLElement | undefined>
|
||||
): void {
|
||||
let resizeListener: ResizeCallback | null = null;
|
||||
let lastArea = 0;
|
||||
|
||||
function getArea() {
|
||||
const el = root.value;
|
||||
if (!el) {
|
||||
return 0;
|
||||
}
|
||||
return el.offsetWidth * el.offsetHeight;
|
||||
}
|
||||
|
||||
watch([root, chart, autoresize], ([root, chart, autoresize], _, cleanup) => {
|
||||
if (root && chart && autoresize) {
|
||||
lastArea = getArea();
|
||||
resizeListener = throttle(() => {
|
||||
if (lastArea === 0) {
|
||||
chart.setOption(Object.create(null), true);
|
||||
chart.resize();
|
||||
chart.setOption(option.value, true);
|
||||
} else {
|
||||
chart.resize();
|
||||
}
|
||||
lastArea = getArea();
|
||||
chart.resize();
|
||||
}, 100);
|
||||
|
||||
addListener(root, resizeListener);
|
||||
@ -39,7 +21,6 @@ export function useAutoresize(
|
||||
|
||||
cleanup(() => {
|
||||
if (resizeListener && root) {
|
||||
lastArea = 0;
|
||||
removeListener(root, resizeListener);
|
||||
}
|
||||
});
|
||||
|
||||
@ -3,14 +3,16 @@ import { EChartsType } from "../types";
|
||||
|
||||
export const LOADING_OPTIONS_KEY = "ecLoadingOptions";
|
||||
|
||||
type UnknownRecord = Record<string, unknown>;
|
||||
|
||||
export function useLoading(
|
||||
chart: Ref<EChartsType | undefined>,
|
||||
loading: Ref<boolean>,
|
||||
loadingOptions: Ref<object | undefined>
|
||||
loadingOptions: Ref<UnknownRecord | undefined>
|
||||
): void {
|
||||
const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {}) as
|
||||
| object
|
||||
| Ref<object>;
|
||||
| UnknownRecord
|
||||
| Ref<UnknownRecord>;
|
||||
const realLoadingOptions = computed(() => ({
|
||||
...unref(defaultLoadingOptions),
|
||||
...loadingOptions?.value
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
></button>
|
||||
</h2>
|
||||
<section v-if="expand.map">
|
||||
<figure style="background-color: #404a59;">
|
||||
<figure style="background-color: #404a59">
|
||||
<v-chart
|
||||
:option="map"
|
||||
:init-options="initOptions"
|
||||
@ -225,7 +225,7 @@
|
||||
>
|
||||
</p>
|
||||
<p><button :disabled="flightLoaded" @click="loadFlights">Load</button></p>
|
||||
<figure style="background-color: #003;">
|
||||
<figure style="background-color: #003">
|
||||
<v-chart
|
||||
ref="flight"
|
||||
:init-options="initOptions"
|
||||
@ -274,7 +274,13 @@
|
||||
import qs from "qs";
|
||||
import VChart from "../ECharts";
|
||||
|
||||
import * as echarts from "echarts/core";
|
||||
import {
|
||||
use,
|
||||
registerMap,
|
||||
registerTheme,
|
||||
connect,
|
||||
disconnect
|
||||
} from "echarts/core";
|
||||
import {
|
||||
BarChart,
|
||||
LineChart,
|
||||
@ -293,11 +299,26 @@ import {
|
||||
LegendComponent,
|
||||
TitleComponent,
|
||||
VisualMapComponent,
|
||||
DatasetComponent
|
||||
DatasetComponent,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent
|
||||
} from "echarts/components";
|
||||
import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
|
||||
// import "echarts-liquidfill";
|
||||
// import logo from "./data/logo";
|
||||
import getBar from "./data/bar";
|
||||
import pie from "./data/pie";
|
||||
import polar from "./data/polar";
|
||||
import scatter from "./data/scatter";
|
||||
import map from "./data/map";
|
||||
import { c1, c2 } from "./data/connect";
|
||||
|
||||
const { use, registerMap, registerTheme } = echarts;
|
||||
// custom theme
|
||||
import theme from "./theme.json";
|
||||
|
||||
// Map of China
|
||||
import chinaMap from "./china.json";
|
||||
import worldMap from "./world.json";
|
||||
|
||||
use([
|
||||
BarChart,
|
||||
@ -317,25 +338,11 @@ use([
|
||||
VisualMapComponent,
|
||||
DatasetComponent,
|
||||
CanvasRenderer,
|
||||
SVGRenderer
|
||||
SVGRenderer,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent
|
||||
]);
|
||||
|
||||
// import "echarts-liquidfill";
|
||||
// import logo from "./data/logo";
|
||||
import getBar from "./data/bar";
|
||||
import pie from "./data/pie";
|
||||
import polar from "./data/polar";
|
||||
import scatter from "./data/scatter";
|
||||
import map from "./data/map";
|
||||
import { c1, c2 } from "./data/connect";
|
||||
|
||||
// custom theme
|
||||
import theme from "./theme.json";
|
||||
|
||||
// Map of China
|
||||
import chinaMap from "./china.json";
|
||||
import worldMap from "./world.json";
|
||||
|
||||
// registering map data
|
||||
registerMap("china", chinaMap);
|
||||
registerMap("world", worldMap);
|
||||
@ -444,7 +451,7 @@ export default {
|
||||
function getAirportCoord(idx) {
|
||||
return [data.airports[idx][3], data.airports[idx][4]];
|
||||
}
|
||||
const routes = data.routes.map(function(airline) {
|
||||
const routes = data.routes.map(airline => {
|
||||
return [getAirportCoord(airline[1]), getAirportCoord(airline[2])];
|
||||
});
|
||||
|
||||
@ -533,7 +540,11 @@ export default {
|
||||
watch: {
|
||||
connected: {
|
||||
handler(value) {
|
||||
echarts[value ? "connect" : "disconnect"]("radiance");
|
||||
if (value) {
|
||||
connect("radiance");
|
||||
} else {
|
||||
disconnect("radiance");
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
||||
@ -12,27 +12,27 @@ export default function getData() {
|
||||
source: [
|
||||
{
|
||||
Product: "Matcha Latte",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
},
|
||||
{
|
||||
Product: "Milk Tea",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
},
|
||||
{
|
||||
Product: "Cheese Cocoa",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
},
|
||||
{
|
||||
Product: "Walnut Brownie",
|
||||
"2015": random(),
|
||||
"2016": random(),
|
||||
"2017": random()
|
||||
2015: random(),
|
||||
2016: random(),
|
||||
2017: random()
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -446,7 +446,7 @@ export default {
|
||||
data: convertData(data),
|
||||
symbolSize: val => val[2] / 10,
|
||||
tooltip: {
|
||||
formatter: function(val) {
|
||||
formatter: function (val) {
|
||||
return val.name + ": " + val.value[2];
|
||||
}
|
||||
},
|
||||
@ -468,7 +468,7 @@ export default {
|
||||
scale: true
|
||||
},
|
||||
tooltip: {
|
||||
formatter: function(val) {
|
||||
formatter: function (val) {
|
||||
return val.name + ": " + val.value[2];
|
||||
}
|
||||
},
|
||||
|
||||
1
src/index.vue2.d.ts
vendored
1
src/index.vue2.d.ts
vendored
@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
declare const LOADING_OPTIONS_KEY = "ecLoadingOptions";
|
||||
declare const THEME_KEY = "ecTheme";
|
||||
declare const INIT_OPTIONS_KEY = "ecInitOptions";
|
||||
|
||||
@ -6,9 +6,9 @@ type Attrs = {
|
||||
// Copied from
|
||||
// https://github.com/vuejs/vue-next/blob/5a7a1b8293822219283d6e267496bec02234b0bc/packages/shared/src/index.ts#L40-L41
|
||||
const onRE = /^on[^a-z]/;
|
||||
export const isOn = (key: string) => onRE.test(key);
|
||||
export const isOn = (key: string): boolean => onRE.test(key);
|
||||
|
||||
export function omitOn(attrs: Attrs) {
|
||||
export function omitOn(attrs: Attrs): Attrs {
|
||||
const result: Attrs = {};
|
||||
for (const key in attrs) {
|
||||
if (!isOn(key)) {
|
||||
|
||||
Reference in New Issue
Block a user