feat: add default style, injectable update-options & loading-options

This commit is contained in:
Justineo
2021-02-22 11:50:43 +08:00
parent aaab149c11
commit b8d9ca7991
7 changed files with 98 additions and 52 deletions

View File

@ -1,13 +1,14 @@
import typescript from "rollup-plugin-typescript2";
import { terser } from "rollup-plugin-terser";
import resolve from "@rollup/plugin-node-resolve";
import postcss from "rollup-plugin-postcss";
import dts from "rollup-plugin-dts";
/** @type {import('rollup').RollupOptions} */
const options = [
{
input: "src/index.ts",
plugins: [typescript()],
plugins: [typescript(), postcss()],
external: ["vue-demi", "echarts/core", "resize-detector"],
output: [
{
@ -50,8 +51,8 @@ const options = [
},
{
input: "src/all.ts",
plugins: [resolve(), typescript()],
external: ["vue-demi", "echarts/core"],
plugins: [resolve(), typescript(), postcss()],
external: ["vue", "echarts", "echarts/core"],
output: [
{
file: "dist/index.umd.js",
@ -59,7 +60,8 @@ const options = [
name: "VueECharts",
sourcemap: true,
globals: {
"vue-demi": "VueDemi",
vue: "Vue",
echarts: "echarts",
"echarts/core": "echarts"
}
},
@ -69,7 +71,8 @@ const options = [
name: "VueECharts",
sourcemap: true,
globals: {
"vue-demi": "VueDemi",
vue: "Vue",
echarts: "echarts",
"echarts/core": "echarts"
},
plugins: [
@ -84,7 +87,7 @@ const options = [
},
{
input: "src/index.ts",
plugins: [dts()],
plugins: [postcss(), dts()],
output: {
file: "dist/index.d.ts",
format: "es"

View File

@ -2,6 +2,7 @@
import {
defineComponent,
ref,
unref,
shallowRef,
toRefs,
watch,
@ -10,10 +11,17 @@ import {
onMounted,
onUnmounted,
h,
PropType
PropType,
watchEffect
} from "vue-demi";
import { init as initChart } from "echarts/core";
import { EChartsType, OptionType } from "./types";
import {
EChartsType,
InitOptions,
Option,
UpdateOptions,
Theme
} from "./types";
import {
usePublicAPI,
useAutoresize,
@ -21,37 +29,49 @@ import {
useLoading,
loadingProps
} from "./composables";
import "./style.css";
type InitParameters = Parameters<typeof initChart>;
type ThemeParameter = InitParameters[1];
type InitOptsParameter = InitParameters[2];
export const INIT_OPTIONS_KEY = "ecInitOptions";
export const UPDATE_OPTIONS_KEY = "ecUpdateOptions";
export { LOADING_OPTIONS_KEY } from "./composables";
export default defineComponent({
name: "echarts",
props: {
option: Object as PropType<OptionType>,
option: Object as PropType<Option>,
theme: {
type: [Object, String] as PropType<ThemeParameter>
type: [Object, String] as PropType<Theme>
},
initOptions: Object as PropType<InitOptsParameter>,
initOptions: Object as PropType<InitOptions>,
updateOptions: Object as PropType<UpdateOptions>,
group: String,
manualUpdate: Boolean,
...autoresizeProps,
...loadingProps
},
setup(props, { attrs }) {
const defaultInitOptions = inject(
"echartsInitOptions",
const defaultInitOptions = inject(INIT_OPTIONS_KEY, {}) as InitOptions;
const defaultUpdateOptions = inject(
UPDATE_OPTIONS_KEY,
{}
) as InitOptsParameter;
) as UpdateOptions;
const root = ref<HTMLElement>();
const chart = shallowRef<EChartsType>();
const manualOption = shallowRef<OptionType>();
const manualOption = shallowRef<Option>();
const realOption = computed(
() => manualOption.value || props.option || Object.create(null)
);
const realInitOptions = computed(() => ({
...defaultInitOptions,
...props.initOptions
}));
const realUpdateOptions = computed(() => ({
...defaultUpdateOptions,
...props.updateOptions
}));
const { autoresize, manualUpdate, loading, loadingOptions } = toRefs(props);
function init(option?: OptionType) {
function init(option?: Option) {
if (chart.value || !root.value) {
return;
}
@ -59,7 +79,7 @@ export default defineComponent({
const instance = (chart.value = initChart(
root.value,
props.theme,
props.initOptions || defaultInitOptions
realInitOptions.value
));
if (props.group) {
@ -67,7 +87,7 @@ export default defineComponent({
}
Object.keys(attrs)
.filter(key => key.indexOf(`on`) === 0)
.filter(key => key.indexOf("on") === 0)
.forEach(key => {
const handler = attrs[key] as any;
@ -82,10 +102,10 @@ export default defineComponent({
}
});
instance.setOption(option || realOption.value, true);
instance.setOption(option || realOption.value, realUpdateOptions.value);
}
function setOption(option: OptionType, ...rest: any[]) {
function setOption(option: Option, updateOptions?: UpdateOptions) {
if (props.manualUpdate) {
manualOption.value = option;
}
@ -93,7 +113,10 @@ export default defineComponent({
if (!chart.value) {
init(option);
} else {
chart.value.setOption(option, ...rest);
chart.value.setOption(option, {
...realUpdateOptions.value,
...updateOptions
});
}
}
@ -104,7 +127,6 @@ export default defineComponent({
}
}
const { autoresize, manualUpdate, loading, loadingOptions } = toRefs(props);
let unwatchOption: (() => void) | null = null;
watch(
manualUpdate,
@ -117,21 +139,14 @@ export default defineComponent({
if (!manualUpdate) {
unwatchOption = watch(
() => props.option,
(val, oldVal) => {
if (!val) {
option => {
if (!option) {
return;
}
if (!chart.value) {
init();
} else {
// mutating `option` will lead to merging
// replacing it with new reference will lead to not merging
// eg.
// `this.option = Object.assign({}, this.option, { ... })`
// will trigger `this.chart.setOption(val, true)
// `this.option.title.text = 'Trends'`
// will trigger `this.chart.setOption(val, false)`
chart.value.setOption(val, val !== oldVal);
chart.value.setOption(option, props.updateOptions);
}
},
{ deep: true }
@ -154,14 +169,11 @@ export default defineComponent({
}
);
watch(
() => props.group,
group => {
if (group && chart.value) {
chart.value.group = group;
watchEffect(() => {
if (props.group && chart.value) {
chart.value.group = props.group;
}
}
);
});
const publicApi = usePublicAPI(chart, init);
@ -177,13 +189,20 @@ export default defineComponent({
onUnmounted(cleanup);
return {
const exposed = {
root,
setOption,
...publicApi
};
},
render() {
return h("div", { ref: "root" });
Object.defineProperty(exposed, "chart", {
get() {
return unref(chart);
}
});
return exposed;
},
render() {
return h("div", { class: "echarts", ref: "root" });
}
});

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Ref } from "vue-demi";
import { EChartsType, OptionType } from "../types";
import { EChartsType, Option } from "../types";
const METHOD_NAMES = [
"getWidth",
@ -24,7 +24,7 @@ type PublicMethods = Pick<EChartsType, MethodName>;
export function usePublicAPI(
chart: Ref<EChartsType | undefined>,
init: (option?: OptionType) => void
init: (option?: Option) => void
) {
function makePublicMethod<T extends MethodName>(
name: T

View File

@ -1,13 +1,13 @@
import { Ref, watch } from "vue-demi";
import { throttle } from "echarts/core";
import { addListener, removeListener, ResizeCallback } from "resize-detector";
import { EChartsType, OptionType } from "../types";
import { EChartsType, Option } from "../types";
export function useAutoresize(
chart: Ref<EChartsType | undefined>,
autoresize: Ref<boolean>,
root: Ref<HTMLElement | undefined>,
option: Ref<OptionType>
option: Ref<Option>
): void {
let resizeListener: ResizeCallback | null = null;
let lastArea = 0;

View File

@ -1,11 +1,19 @@
import { Ref, watchEffect } from "vue-demi";
import { inject, computed, Ref, watchEffect } from "vue-demi";
import { EChartsType } from "../types";
export const LOADING_OPTIONS_KEY = "ecLoadingOptions";
export function useLoading(
chart: Ref<EChartsType | undefined>,
loading: Ref<boolean>,
loadingOptions?: Ref<object | undefined>
): void {
const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {}) as object;
const realLoadingOptions = computed(() => ({
...defaultLoadingOptions,
...loadingOptions?.value
}));
watchEffect(() => {
const instance = chart.value;
if (!instance) {
@ -13,7 +21,7 @@ export function useLoading(
}
if (loading.value) {
instance.showLoading(loadingOptions?.value);
instance.showLoading(realLoadingOptions.value);
} else {
instance.hideLoading();
}

1
src/style.css Normal file
View File

@ -0,0 +1 @@
.echarts{width:100%;height:100%}

View File

@ -1,5 +1,20 @@
import { init } from "echarts/core";
export type EChartsType = ReturnType<typeof init>;
type InitType = typeof init;
export type InitParameters = Parameters<InitType>;
export type Theme = NonNullable<InitParameters[1]>;
export type InitOptions = NonNullable<InitParameters[2]>;
export type EChartsType = ReturnType<InitType>;
type SetOptionType = EChartsType["setOption"];
export type OptionType = Parameters<SetOptionType>[0];
export type Option = Parameters<SetOptionType>[0];
// TODO: Wait for apache/echarts#14289 to ship in v5.1,
// so that we can use SetOptionOpts directly
export interface UpdateOptions {
notMerge?: boolean;
lazyUpdate?: boolean;
silent?: boolean;
replaceMerge?: any;
transition?: any;
}