From b5700bd0b1e63224bfe9e57bde4968041e26ffd1 Mon Sep 17 00:00:00 2001 From: ming4762 Date: Sun, 13 Apr 2025 20:03:18 +0800 Subject: [PATCH 01/12] perf: improve `autoSelect` of `ApiComponent` (#5936) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复autoSelect不生效的问题,props.valueField已经被omit了 * feat: ApiComponent autoSelect支持使用函数,可以满足灵活性要求更高的场景 --- .../common-ui/vben-api-component.md | 3 +- .../api-component/api-component.vue | 38 ++++++++++++------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/src/components/common-ui/vben-api-component.md b/docs/src/components/common-ui/vben-api-component.md index 17b8d306..33f7f045 100644 --- a/docs/src/components/common-ui/vben-api-component.md +++ b/docs/src/components/common-ui/vben-api-component.md @@ -151,7 +151,7 @@ function fetchApi(): Promise> { | options | 直接传入选项数据,也作为api返回空数据时的后备数据 | `OptionsItem[]` | - | - | | visibleEvent | 触发重新请求数据的事件名 | `string` | - | - | | loadingSlot | 目标组件的插槽名称,用来显示一个"加载中"的图标 | `string` | - | - | -| autoSelect | 自动设置选项 | `'first' \| 'last' \| 'none'\| false` | `false` | >5.5.4 | +| autoSelect | 自动设置选项 | `'first' \| 'last' \| 'one'\| (item: OptionsItem[]) => OptionsItem \| false` | `false` | >5.5.4 | #### autoSelect 自动设置选项 @@ -160,6 +160,7 @@ function fetchApi(): Promise> { - `first`:自动选择第一个选项 - `last`:自动选择最后一个选项 - `one`:有且仅有一个选项时,自动选择它 +- `函数`:自定义选择逻辑,函数的参数为options,返回值为选择的选项 - false:不自动选择选项 ### Methods 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 b3b33025..dcbacd4e 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 @@ -59,9 +59,15 @@ interface Props { * - `first`:自动选择第一个选项 * - `last`:自动选择最后一个选项 * - `one`: 当请求的结果只有一个选项时,自动选择该选项 + * - 函数:自定义选择逻辑,函数的参数为请求的结果数组,返回值为选择的选项 * - false:不自动选择(默认) */ - autoSelect?: 'first' | 'last' | 'one' | false; + autoSelect?: + | 'first' + | 'last' + | 'one' + | ((item: OptionsItem[]) => OptionsItem) + | false; } defineOptions({ name: 'ApiComponent', inheritAttrs: false }); @@ -209,24 +215,28 @@ function emitChange() { unref(getOptions).length > 0 ) { let firstOption; - switch (props.autoSelect) { - case 'first': { - firstOption = unref(getOptions)[0]; - break; - } - case 'last': { - firstOption = unref(getOptions)[unref(getOptions).length - 1]; - break; - } - case 'one': { - if (unref(getOptions).length === 1) { + if (isFunction(props.autoSelect)) { + firstOption = props.autoSelect(unref(getOptions)); + } else { + switch (props.autoSelect) { + case 'first': { firstOption = unref(getOptions)[0]; + break; + } + case 'last': { + firstOption = unref(getOptions)[unref(getOptions).length - 1]; + break; + } + case 'one': { + if (unref(getOptions).length === 1) { + firstOption = unref(getOptions)[0]; + } + break; } - break; } } - if (firstOption) modelValue.value = firstOption[props.valueField]; + if (firstOption) modelValue.value = firstOption.value; } emit('optionsChange', unref(getOptions)); } From afce9dc5c06531e83d076eefeffc57debac126b7 Mon Sep 17 00:00:00 2001 From: ming4762 Date: Sun, 13 Apr 2025 23:02:07 +0800 Subject: [PATCH 02/12] perf: improve `destroyOnClose` for `VbenModal` (#5935) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 优化Vben Modal destroyOnClose,解决destroyOnClose=false,Modal依旧会被销毁的问题 影响范围(重要):destroyOnClose默认为true,这会导致所有的modal都会默认渲染到body radix-vue Dialog组件默认会销毁挂载的组件,所以即使destroyOnClose=false,Modal依旧会被销毁的问题 对于一些大表单重复渲染导致卡顿,ApiComponent也会频繁的加载数据 * fix: modal closing animation --------- Co-authored-by: Netfan --- docs/src/components/common-ui/vben-modal.md | 3 +-- .../ui-kit/popup-ui/src/modal/modal-api.ts | 1 + .../@core/ui-kit/popup-ui/src/modal/modal.ts | 8 +++--- .../@core/ui-kit/popup-ui/src/modal/modal.vue | 23 ++++++++++++++-- .../ui-kit/popup-ui/src/modal/use-modal.ts | 26 ++----------------- .../views/examples/modal/auto-height-demo.vue | 11 +++++--- .../views/examples/modal/in-content-demo.vue | 4 +-- playground/src/views/examples/modal/index.vue | 2 +- 8 files changed, 39 insertions(+), 39 deletions(-) diff --git a/docs/src/components/common-ui/vben-modal.md b/docs/src/components/common-ui/vben-modal.md index 39b88cf9..72fdf9cf 100644 --- a/docs/src/components/common-ui/vben-modal.md +++ b/docs/src/components/common-ui/vben-modal.md @@ -60,7 +60,6 @@ Modal 内的内容一般业务中,会比较复杂,所以我们可以将 moda - `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 -- 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。 - 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。 ::: @@ -84,7 +83,7 @@ const [Modal, modalApi] = useVbenModal({ | --- | --- | --- | --- | | appendToMain | 是否挂载到内容区域(默认挂载到body) | `boolean` | `false` | | connectedComponent | 连接另一个Modal组件 | `Component` | - | -| destroyOnClose | 关闭时销毁`connectedComponent` | `boolean` | `false` | +| destroyOnClose | 关闭时销毁 | `boolean` | `false` | | title | 标题 | `string\|slot` | - | | titleTooltip | 标题提示信息 | `string\|slot` | - | | description | 描述信息 | `string\|slot` | - | diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts b/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts index 97790969..27aa8216 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts @@ -44,6 +44,7 @@ export class ModalApi { confirmDisabled: false, confirmLoading: false, contentClass: '', + destroyOnClose: true, draggable: false, footer: true, footerClass: '', diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal.ts b/packages/@core/ui-kit/popup-ui/src/modal/modal.ts index 9f86ab8c..2dbab9e4 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal.ts +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal.ts @@ -60,6 +60,10 @@ export interface ModalProps { * 弹窗描述 */ description?: string; + /** + * 在关闭时销毁弹窗 + */ + destroyOnClose?: boolean; /** * 是否可拖拽 * @default false @@ -153,10 +157,6 @@ export interface ModalApiOptions extends ModalState { * 独立的弹窗组件 */ connectedComponent?: Component; - /** - * 在关闭时销毁弹窗。仅在使用 connectedComponent 时有效 - */ - destroyOnClose?: boolean; /** * 关闭前的回调,返回 false 可以阻止关闭 * @returns diff --git a/packages/@core/ui-kit/popup-ui/src/modal/modal.vue b/packages/@core/ui-kit/popup-ui/src/modal/modal.vue index 6fe3d621..000cba9f 100644 --- a/packages/@core/ui-kit/popup-ui/src/modal/modal.vue +++ b/packages/@core/ui-kit/popup-ui/src/modal/modal.vue @@ -1,7 +1,7 @@ diff --git a/playground/src/views/examples/modal/in-content-demo.vue b/playground/src/views/examples/modal/in-content-demo.vue index b51d363f..7ffe7b77 100644 --- a/playground/src/views/examples/modal/in-content-demo.vue +++ b/playground/src/views/examples/modal/in-content-demo.vue @@ -24,7 +24,7 @@ const value = ref(); title="基础弹窗示例" title-tooltip="标题提示内容" > - 此弹窗指定在内容区域打开 - + 此弹窗指定在内容区域打开,并且在关闭之后弹窗内容不会被销毁 + diff --git a/playground/src/views/examples/modal/index.vue b/playground/src/views/examples/modal/index.vue index 7401737a..3ed6cdea 100644 --- a/playground/src/views/examples/modal/index.vue +++ b/playground/src/views/examples/modal/index.vue @@ -198,7 +198,7 @@ async function openPrompt() { - +

在内容区域打开弹窗的示例