Skip to content

Commit d1ea0fb

Browse files
committed
feat: support getter in provide/inject
1 parent 49e2639 commit d1ea0fb

File tree

5 files changed

+73
-18
lines changed

5 files changed

+73
-18
lines changed

README.md

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -257,22 +257,53 @@ As Vue-ECharts binds events to the ECharts instance by default, there is some ca
257257

258258
### Provide / Inject
259259

260-
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:
260+
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:
261261

262262
<details>
263-
<summary>Vue 3</summary>
263+
<summary>Composition API</summary>
264264

265265
```js
266266
import { THEME_KEY } from 'vue-echarts'
267267
import { provide } from 'vue'
268268

269-
// composition API
270269
provide(THEME_KEY, 'dark')
271270

272-
// options API
273-
{
274-
provide: {
275-
[THEME_KEY]: 'dark'
271+
// or provide a reactive state
272+
const theme = ref('dark')
273+
provide(THEME_KEY, computed(() => theme.value))
274+
275+
// getter is also supported
276+
provide(THEME_KEY, () => theme.value)
277+
```
278+
279+
</details>
280+
281+
<details>
282+
<summary>Options API</summary>
283+
284+
```js
285+
import { THEME_KEY } from 'vue-echarts'
286+
import { computed } from 'vue'
287+
288+
export default {
289+
{
290+
provide: {
291+
[THEME_KEY]: 'dark'
292+
}
293+
}
294+
}
295+
296+
// Or make injections reactive
297+
export default {
298+
data() {
299+
return {
300+
theme: 'dark'
301+
}
302+
},
303+
provide() {
304+
return {
305+
[THEME_KEY]: computed(() => this.theme)
306+
}
276307
}
277308
}
278309
```

src/ECharts.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import {
1111
onBeforeUnmount,
1212
h,
1313
nextTick,
14-
watchEffect,
15-
unref
14+
watchEffect
1615
} from "vue";
1716
import { init as initChart } from "echarts/core";
1817

@@ -23,7 +22,7 @@ import {
2322
useLoading,
2423
loadingProps
2524
} from "./composables";
26-
import { isOn, omitOn } from "./utils";
25+
import { isOn, omitOn, toValue } from "./utils";
2726
import { register, TAG_NAME } from "./wc";
2827

2928
import type { PropType, InjectionKey } from "vue";
@@ -82,12 +81,14 @@ export default defineComponent({
8281
const realOption = computed(
8382
() => manualOption.value || props.option || null
8483
);
85-
const realTheme = computed(() => props.theme || unref(defaultTheme) || {});
84+
const realTheme = computed(
85+
() => props.theme || toValue(defaultTheme) || {}
86+
);
8687
const realInitOptions = computed(
87-
() => props.initOptions || unref(defaultInitOptions) || {}
88+
() => props.initOptions || toValue(defaultInitOptions) || {}
8889
);
8990
const realUpdateOptions = computed(
90-
() => props.updateOptions || unref(defaultUpdateOptions) || {}
91+
() => props.updateOptions || toValue(defaultUpdateOptions) || {}
9192
);
9293
const nonEventAttrs = computed(() => omitOn(attrs));
9394
const nativeListeners: Record<string, unknown> = {};

src/composables/loading.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { inject, computed, watchEffect, unref } from "vue";
1+
import { inject, computed, watchEffect } from "vue";
2+
import { toValue } from "../utils";
23

34
import type { Ref, InjectionKey, PropType } from "vue";
45
import type { EChartsType, LoadingOptions } from "../types";
@@ -15,7 +16,7 @@ export function useLoading(
1516
): void {
1617
const defaultLoadingOptions = inject(LOADING_OPTIONS_KEY, {});
1718
const realLoadingOptions = computed(() => ({
18-
...(unref(defaultLoadingOptions) || {}),
19+
...(toValue(defaultLoadingOptions) || {}),
1920
...loadingOptions?.value
2021
}));
2122

src/types.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import { init } from "echarts/core";
22

33
import type { SetOptionOpts, ECElementEvent, ElementEvent } from "echarts/core";
4-
import type { MaybeRef } from "vue";
5-
6-
export type Injection<T> = MaybeRef<T | null>;
4+
import type { Ref, ShallowRef, WritableComputedRef, ComputedRef } from "vue";
5+
6+
export type MaybeRef<T = any> =
7+
| T
8+
| Ref<T>
9+
| ShallowRef<T>
10+
| WritableComputedRef<T>;
11+
export type MaybeRefOrGetter<T = any> =
12+
| MaybeRef<T>
13+
| ComputedRef<T>
14+
| (() => T);
15+
export type Injection<T> = MaybeRefOrGetter<T | null>;
716

817
type InitType = typeof init;
918
export type InitParameters = Parameters<InitType>;

src/utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { MaybeRefOrGetter } from "./types";
2+
import { unref } from "vue";
3+
14
type Attrs = {
25
// eslint-disable-next-line @typescript-eslint/no-explicit-any
36
[key: string]: any;
@@ -18,3 +21,13 @@ export function omitOn(attrs: Attrs): Attrs {
1821

1922
return result;
2023
}
24+
25+
// Copied from
26+
// https://github.com/vuejs/core/blob/3cb4db21efa61852b0541475b4ddf57fdec4c479/packages/shared/src/general.ts#L49-L50
27+
const isFunction = (val: unknown): val is Function => typeof val === "function";
28+
29+
// Copied from
30+
// https://github.com/vuejs/core/blob/3cb4db21efa61852b0541475b4ddf57fdec4c479/packages/reactivity/src/ref.ts#L246-L248
31+
export function toValue<T>(source: MaybeRefOrGetter<T>): T {
32+
return isFunction(source) ? source() : unref(source);
33+
}

0 commit comments

Comments
 (0)