diff --git a/README.md b/README.md index 1438d3d..49bed52 100644 --- a/README.md +++ b/README.md @@ -257,22 +257,53 @@ As Vue-ECharts binds events to the ECharts instance by default, there is some ca ### Provide / Inject -Vue-ECharts provides provide/inject API for `theme`, `init-options`, `update-options` and `loading-options` to help configuring contextual options. eg. for `init-options` you can use the provide API like this: +Vue-ECharts provides provide/inject API for `theme`, `init-options`, `update-options` and `loading-options` to help configuring contextual options. eg. for `theme` you can use the provide API like this:
-Vue 3 +Composition API ```js import { THEME_KEY } from 'vue-echarts' import { provide } from 'vue' -// composition API provide(THEME_KEY, 'dark') -// options API -{ - provide: { - [THEME_KEY]: 'dark' +// or provide a reactive state +const theme = ref('dark') +provide(THEME_KEY, computed(() => theme.value)) + +// getter is also supported +provide(THEME_KEY, () => theme.value) +``` + +
+ +
+Options API + +```js +import { THEME_KEY } from 'vue-echarts' +import { computed } from 'vue' + +export default { + { + provide: { + [THEME_KEY]: 'dark' + } + } +} + +// Or make injections reactive +export default { + data() { + return { + theme: 'dark' + } + }, + provide() { + return { + [THEME_KEY]: computed(() => this.theme) + } } } ``` diff --git a/src/ECharts.ts b/src/ECharts.ts index 3ec6ecb..9721246 100644 --- a/src/ECharts.ts +++ b/src/ECharts.ts @@ -11,8 +11,7 @@ import { onBeforeUnmount, h, nextTick, - watchEffect, - unref + watchEffect } from "vue"; import { init as initChart } from "echarts/core"; @@ -23,7 +22,7 @@ import { useLoading, loadingProps } from "./composables"; -import { isOn, omitOn } from "./utils"; +import { isOn, omitOn, toValue } from "./utils"; import { register, TAG_NAME } from "./wc"; import type { PropType, InjectionKey } from "vue"; @@ -82,12 +81,14 @@ export default defineComponent({ const realOption = computed( () => manualOption.value || props.option || null ); - const realTheme = computed(() => props.theme || unref(defaultTheme) || {}); + const realTheme = computed( + () => props.theme || toValue(defaultTheme) || {} + ); const realInitOptions = computed( - () => props.initOptions || unref(defaultInitOptions) || {} + () => props.initOptions || toValue(defaultInitOptions) || {} ); const realUpdateOptions = computed( - () => props.updateOptions || unref(defaultUpdateOptions) || {} + () => props.updateOptions || toValue(defaultUpdateOptions) || {} ); const nonEventAttrs = computed(() => omitOn(attrs)); const nativeListeners: Record = {}; diff --git a/src/composables/loading.ts b/src/composables/loading.ts index e0c07f0..37a3341 100644 --- a/src/composables/loading.ts +++ b/src/composables/loading.ts @@ -1,4 +1,5 @@ -import { inject, computed, watchEffect, unref } from "vue"; +import { inject, computed, watchEffect } from "vue"; +import { toValue } from "../utils"; import type { Ref, InjectionKey, PropType } from "vue"; import type { EChartsType, LoadingOptions } from "../types"; @@ -15,7 +16,7 @@ export function useLoading( ): void { const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {}); const realLoadingOptions = computed(() => ({ - ...(unref(defaultLoadingOptions) || {}), + ...(toValue(defaultLoadingOptions) || {}), ...loadingOptions?.value })); diff --git a/src/types.ts b/src/types.ts index 71f9b49..97e82f7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,18 @@ import { init } from "echarts/core"; import type { SetOptionOpts, ECElementEvent, ElementEvent } from "echarts/core"; -import type { MaybeRef } from "vue"; +import type { Ref, ShallowRef, WritableComputedRef, ComputedRef } from "vue"; -export type Injection = MaybeRef; +export type MaybeRef = + | T + | Ref + | ShallowRef + | WritableComputedRef; +export type MaybeRefOrGetter = + | MaybeRef + | ComputedRef + | (() => T); +export type Injection = MaybeRefOrGetter; type InitType = typeof init; export type InitParameters = Parameters; diff --git a/src/utils.ts b/src/utils.ts index 8ac89ee..8792277 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,6 @@ +import type { MaybeRefOrGetter } from "./types"; +import { unref } from "vue"; + type Attrs = { // eslint-disable-next-line @typescript-eslint/no-explicit-any [key: string]: any; @@ -18,3 +21,13 @@ export function omitOn(attrs: Attrs): Attrs { return result; } + +// Copied from +// https://github.com/vuejs/core/blob/3cb4db21efa61852b0541475b4ddf57fdec4c479/packages/shared/src/general.ts#L49-L50 +const isFunction = (val: unknown): val is Function => typeof val === "function"; + +// Copied from +// https://github.com/vuejs/core/blob/3cb4db21efa61852b0541475b4ddf57fdec4c479/packages/reactivity/src/ref.ts#L246-L248 +export function toValue(source: MaybeRefOrGetter): T { + return isFunction(source) ? source() : unref(source); +}