feat: support getter in provide/inject

This commit is contained in:
Yue JIN
2025-05-12 19:08:14 +08:00
committed by GU Yiling
parent 349644f913
commit f81fd99c1a
5 changed files with 72 additions and 17 deletions

View File

@ -257,23 +257,54 @@ 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:
<details>
<summary>Vue 3</summary>
<summary>Composition API</summary>
```js
import { THEME_KEY } from 'vue-echarts'
import { provide } from 'vue'
// composition API
provide(THEME_KEY, 'dark')
// options API
{
// or provide a reactive state
const theme = ref('dark')
provide(THEME_KEY, computed(() => theme.value))
// getter is also supported
provide(THEME_KEY, () => theme.value)
```
</details>
<details>
<summary>Options API</summary>
```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)
}
}
}
```

View File

@ -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<string, unknown> = {};

View File

@ -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
}));

View File

@ -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<T> = MaybeRef<T | null>;
export type MaybeRef<T = any> =
| T
| Ref<T>
| ShallowRef<T>
| WritableComputedRef<T>;
export type MaybeRefOrGetter<T = any> =
| MaybeRef<T>
| ComputedRef<T>
| (() => T);
export type Injection<T> = MaybeRefOrGetter<T | null>;
type InitType = typeof init;
export type InitParameters = Parameters<InitType>;

View File

@ -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<T>(source: MaybeRefOrGetter<T>): T {
return isFunction(source) ? source() : unref(source);
}