Skip to content

Commit fee811d

Browse files
authored
fix: 优化组件方法透传并新增表单弹窗示例 (#6443)
1 parent 78076e7 commit fee811d

File tree

7 files changed

+131
-77
lines changed

7 files changed

+131
-77
lines changed

apps/web-antd/src/adapter/component/index.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@ import type { Component } from 'vue';
88
import type { BaseFormComponentType } from '@vben/common-ui';
99
import type { Recordable } from '@vben/types';
1010

11-
import {
12-
defineAsyncComponent,
13-
defineComponent,
14-
getCurrentInstance,
15-
h,
16-
ref,
17-
} from 'vue';
11+
import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
1812

1913
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
2014
import { $t } from '@vben/locales';
@@ -82,16 +76,15 @@ const withDefaultPlaceholder = <T extends Component>(
8276
$t(`ui.placeholder.${type}`);
8377
// 透传组件暴露的方法
8478
const innerRef = ref();
85-
const publicApi: Recordable<any> = {};
86-
expose(publicApi);
87-
const instance = getCurrentInstance();
88-
instance?.proxy?.$nextTick(() => {
89-
for (const key in innerRef.value) {
90-
if (typeof innerRef.value[key] === 'function') {
91-
publicApi[key] = innerRef.value[key];
92-
}
93-
}
94-
});
79+
expose(
80+
new Proxy(
81+
{},
82+
{
83+
get: (_target, key) => innerRef.value?.[key],
84+
has: (_target, key) => key in (innerRef.value || {}),
85+
},
86+
),
87+
);
9588
return () =>
9689
h(
9790
component,

apps/web-ele/src/adapter/component/index.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@ import type { Component } from 'vue';
88
import type { BaseFormComponentType } from '@vben/common-ui';
99
import type { Recordable } from '@vben/types';
1010

11-
import {
12-
defineAsyncComponent,
13-
defineComponent,
14-
getCurrentInstance,
15-
h,
16-
ref,
17-
} from 'vue';
11+
import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
1812

1913
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
2014
import { $t } from '@vben/locales';
@@ -139,16 +133,15 @@ const withDefaultPlaceholder = <T extends Component>(
139133
$t(`ui.placeholder.${type}`);
140134
// 透传组件暴露的方法
141135
const innerRef = ref();
142-
const publicApi: Recordable<any> = {};
143-
expose(publicApi);
144-
const instance = getCurrentInstance();
145-
instance?.proxy?.$nextTick(() => {
146-
for (const key in innerRef.value) {
147-
if (typeof innerRef.value[key] === 'function') {
148-
publicApi[key] = innerRef.value[key];
149-
}
150-
}
151-
});
136+
expose(
137+
new Proxy(
138+
{},
139+
{
140+
get: (_target, key) => innerRef.value?.[key],
141+
has: (_target, key) => key in (innerRef.value || {}),
142+
},
143+
),
144+
);
152145
return () =>
153146
h(
154147
component,

apps/web-naive/src/adapter/component/index.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@ import type { Component } from 'vue';
88
import type { BaseFormComponentType } from '@vben/common-ui';
99
import type { Recordable } from '@vben/types';
1010

11-
import {
12-
defineAsyncComponent,
13-
defineComponent,
14-
getCurrentInstance,
15-
h,
16-
ref,
17-
} from 'vue';
11+
import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
1812

1913
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
2014
import { $t } from '@vben/locales';
@@ -85,16 +79,15 @@ const withDefaultPlaceholder = <T extends Component>(
8579
$t(`ui.placeholder.${type}`);
8680
// 透传组件暴露的方法
8781
const innerRef = ref();
88-
const publicApi: Recordable<any> = {};
89-
expose(publicApi);
90-
const instance = getCurrentInstance();
91-
instance?.proxy?.$nextTick(() => {
92-
for (const key in innerRef.value) {
93-
if (typeof innerRef.value[key] === 'function') {
94-
publicApi[key] = innerRef.value[key];
95-
}
96-
}
97-
});
82+
expose(
83+
new Proxy(
84+
{},
85+
{
86+
get: (_target, key) => innerRef.value?.[key],
87+
has: (_target, key) => key in (innerRef.value || {}),
88+
},
89+
),
90+
);
9891
return () =>
9992
h(
10093
component,

apps/web-naive/src/views/demos/form/basic.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<script lang="ts" setup>
2-
import { Page } from '@vben/common-ui';
2+
import { Page, useVbenModal } from '@vben/common-ui';
33
44
import { NButton, NCard, useMessage } from 'naive-ui';
55
66
import { useVbenForm } from '#/adapter/form';
77
import { getAllMenusApi } from '#/api';
88
9+
import modalDemo from './modal.vue';
10+
911
const message = useMessage();
1012
const [Form, formApi] = useVbenForm({
1113
commonConfig: {
@@ -143,6 +145,10 @@ function setFormValues() {
143145
date: Date.now(),
144146
});
145147
}
148+
149+
const [Modal, modalApi] = useVbenModal({
150+
connectedComponent: modalDemo,
151+
});
146152
</script>
147153
<template>
148154
<Page
@@ -152,8 +158,12 @@ function setFormValues() {
152158
<NCard title="基础表单">
153159
<template #header-extra>
154160
<NButton type="primary" @click="setFormValues">设置表单值</NButton>
161+
<NButton type="primary" @click="modalApi.open()" class="ml-2">
162+
打开弹窗
163+
</NButton>
155164
</template>
156165
<Form />
157166
</NCard>
167+
<Modal />
158168
</Page>
159169
</template>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<script lang="ts" setup>
2+
import { useVbenModal } from '@vben/common-ui';
3+
4+
import { useVbenForm } from '#/adapter/form';
5+
6+
defineOptions({
7+
name: 'FormModelDemo',
8+
});
9+
10+
const [Form, formApi] = useVbenForm({
11+
schema: [
12+
{
13+
component: 'Input',
14+
componentProps: {
15+
placeholder: '请输入',
16+
},
17+
fieldName: 'field1',
18+
label: '字段1',
19+
rules: 'required',
20+
},
21+
{
22+
component: 'Input',
23+
componentProps: {
24+
placeholder: '请输入',
25+
},
26+
fieldName: 'field2',
27+
label: '字段2',
28+
rules: 'required',
29+
},
30+
{
31+
component: 'Select',
32+
componentProps: {
33+
options: [
34+
{ label: '选项1', value: '1' },
35+
{ label: '选项2', value: '2' },
36+
],
37+
placeholder: '请输入',
38+
},
39+
fieldName: 'field3',
40+
label: '字段3',
41+
rules: 'required',
42+
},
43+
],
44+
showDefaultActions: false,
45+
});
46+
47+
const [Modal, modalApi] = useVbenModal({
48+
fullscreenButton: false,
49+
onCancel() {
50+
modalApi.close();
51+
},
52+
onConfirm: async () => {
53+
await formApi.validateAndSubmitForm();
54+
// modalApi.close();
55+
},
56+
onOpenChange(isOpen: boolean) {
57+
if (isOpen) {
58+
const { values } = modalApi.getData<Record<string, any>>();
59+
if (values) {
60+
formApi.setValues(values);
61+
}
62+
}
63+
},
64+
title: '内嵌表单示例',
65+
});
66+
</script>
67+
<template>
68+
<Modal>
69+
<Form />
70+
</Modal>
71+
</template>

playground/src/adapter/component/index.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@ import type { Component } from 'vue';
88
import type { BaseFormComponentType } from '@vben/common-ui';
99
import type { Recordable } from '@vben/types';
1010

11-
import {
12-
defineAsyncComponent,
13-
defineComponent,
14-
getCurrentInstance,
15-
h,
16-
ref,
17-
} from 'vue';
11+
import { defineAsyncComponent, defineComponent, h, ref } from 'vue';
1812

1913
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
2014
import { $t } from '@vben/locales';
@@ -82,16 +76,24 @@ const withDefaultPlaceholder = <T extends Component>(
8276
$t(`ui.placeholder.${type}`);
8377
// 透传组件暴露的方法
8478
const innerRef = ref();
85-
const publicApi: Recordable<any> = {};
86-
expose(publicApi);
87-
const instance = getCurrentInstance();
88-
instance?.proxy?.$nextTick(() => {
89-
for (const key in innerRef.value) {
90-
if (typeof innerRef.value[key] === 'function') {
91-
publicApi[key] = innerRef.value[key];
92-
}
93-
}
94-
});
79+
// const publicApi: Recordable<any> = {};
80+
expose(
81+
new Proxy(
82+
{},
83+
{
84+
get: (_target, key) => innerRef.value?.[key],
85+
has: (_target, key) => key in (innerRef.value || {}),
86+
},
87+
),
88+
);
89+
// const instance = getCurrentInstance();
90+
// instance?.proxy?.$nextTick(() => {
91+
// for (const key in innerRef.value) {
92+
// if (typeof innerRef.value[key] === 'function') {
93+
// publicApi[key] = innerRef.value[key];
94+
// }
95+
// }
96+
// });
9597
return () =>
9698
h(
9799
component,

pnpm-lock.yaml

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)