From 19254f5244a173182d30df234a728d0d3e85aa5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=9E=E5=8F=AF=20=C2=B7=20YU=20KE?= <1798456934@qq.com> Date: Mon, 7 Sep 2026 21:55:37 +0800 Subject: [PATCH] fix(@vben/common-ui): fetch ApiComponent options after late API binding (#8371) * fix(common-ui): fetch api options after late binding * test(common-ui): assert late api options payload --- .changeset/calm-api-selects-load.md | 5 +++ .../__tests__/api-component.test.ts | 35 +++++++++++++++++++ .../api-component/api-component.vue | 6 ++-- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 .changeset/calm-api-selects-load.md diff --git a/.changeset/calm-api-selects-load.md b/.changeset/calm-api-selects-load.md new file mode 100644 index 000000000..3025d66e9 --- /dev/null +++ b/.changeset/calm-api-selects-load.md @@ -0,0 +1,5 @@ +--- +'@vben/common-ui': patch +--- + +fix(@vben/common-ui): fetch ApiComponent options when an API is provided after mount diff --git a/packages/effects/common-ui/src/components/api-component/__tests__/api-component.test.ts b/packages/effects/common-ui/src/components/api-component/__tests__/api-component.test.ts index a3a7a6e06..da751e2f3 100644 --- a/packages/effects/common-ui/src/components/api-component/__tests__/api-component.test.ts +++ b/packages/effects/common-ui/src/components/api-component/__tests__/api-component.test.ts @@ -1,3 +1,5 @@ +import type { ApiComponentProps } from '../types'; + import { mount } from '@vue/test-utils'; import { defineComponent, h, markRaw, nextTick, ref } from 'vue'; @@ -128,4 +130,37 @@ describe('api-component.vue', () => { expect(handleUpdate).toHaveBeenCalledWith('selected'); expect(input.props('modelValue')).toBe('selected'); }); + + it('fetches when the api is provided after mount', async () => { + const api = vi + .fn() + .mockResolvedValue([{ label: 'Loaded', value: 'loaded' }]); + const apiRef = ref(); + const Harness = defineComponent({ + setup() { + return () => + h(ApiComponent, { + api: apiRef.value, + component: markRaw(ModelValueInput), + }); + }, + }); + + const wrapper = mount(Harness); + expect(api).not.toHaveBeenCalled(); + + apiRef.value = api; + await nextTick(); + + expect(api).toHaveBeenCalledTimes(1); + await vi.waitFor(() => { + const events = wrapper + .findComponent(ApiComponent) + .emitted('optionsChange'); + const lastEvent = events?.at(-1)?.[0]; + expect(lastEvent).toEqual([ + expect.objectContaining({ label: 'Loaded', value: 'loaded' }), + ]); + }); + }); }); diff --git a/packages/effects/common-ui/src/components/api-component/api-component.vue b/packages/effects/common-ui/src/components/api-component/api-component.vue index 1ea19380a..73d390a23 100644 --- a/packages/effects/common-ui/src/components/api-component/api-component.vue +++ b/packages/effects/common-ui/src/components/api-component/api-component.vue @@ -200,9 +200,9 @@ const mergedParams = computed(() => { }); watch( - mergedParams, - (value, oldValue) => { - if (isEqual(value, oldValue)) { + [() => props.api, mergedParams], + ([api, value], [oldApi, oldValue]) => { + if (api === oldApi && isEqual(value, oldValue)) { return; } fetchApi();