perf(drawer): perf drawer
| | |
| | | - 表单组件现在支持直接传入 model 直接进行 set 操作,参考**组件->弹窗扩展->打开弹窗并传递数据** |
| | | |
| | | - modal 的 useModalInner 现在支持传入回调函数,用于接收外部`transferModalData`传进来的值, |
| | | |
| | | - 用于处理打开弹窗对表单等组件的设置值。参考**组件->弹窗扩展->打开弹窗并传递数据** |
| | | - `receiveModalDataRef`这个值暂时保留。尽量少用。后续可能会删除。 |
| | | |
| | | - drawer 的 useDrawerInner 现在支持传入回调函数,用于接收外部`transferModalData`传进来的值, |
| | | - 用于处理打开抽屉对表单等组件的设置值。参考**组件->抽屉扩展->打开抽屉并传递数据** |
| | | - `receiveModalDataRef`这个值暂时保留。尽量少用。后续可能会删除。 |
| | | |
| | | ### ✨ Refactor |
| | | |
| | | - 表单代码优化重构 |
| | |
| | | import { Drawer, Row, Col, Button } from 'ant-design-vue'; |
| | | import type { DrawerInstance, DrawerProps } from './types'; |
| | | |
| | | import { defineComponent, ref, computed, watchEffect, watch, unref, nextTick, toRaw } from 'vue'; |
| | | import { Drawer, Row, Col, Button } from 'ant-design-vue'; |
| | | |
| | | import { BasicTitle } from '/@/components/Basic'; |
| | | import { FullLoading } from '/@/components/Loading/index'; |
| | | |
| | | import { getSlot } from '/@/utils/helper/tsxHelper'; |
| | | |
| | | import { DrawerInstance, DrawerProps } from './types'; |
| | | import { LeftOutlined } from '@ant-design/icons-vue'; |
| | | |
| | | import { basicProps } from './props'; |
| | | |
| | | import { getSlot } from '/@/utils/helper/tsxHelper'; |
| | | import { isFunction, isNumber } from '/@/utils/is'; |
| | | import { LeftOutlined } from '@ant-design/icons-vue'; |
| | | import { buildUUID } from '/@/utils/uuid'; |
| | | import { deepMerge } from '/@/utils'; |
| | | |
| | | import './index.less'; |
| | | |
| | | const prefixCls = 'basic-drawer'; |
| | |
| | | |
| | | const getProps = computed(() => { |
| | | const opt: any = { |
| | | // @ts-ignore |
| | | placement: 'right', |
| | | ...attrs, |
| | | ...props, |
| | |
| | | opt.wrapClassName = opt.wrapClassName |
| | | ? `${opt.wrapClassName} ${prefixCls}__detail` |
| | | : `${prefixCls}__detail`; |
| | | // opt.maskClosable = false; |
| | | if (!opt.getContainer) { |
| | | opt.getContainer = `.default-layout__main`; |
| | | } |
| | |
| | | {showOkBtn && ( |
| | | <Button |
| | | type={okType} |
| | | {...okButtonProps} |
| | | loading={confirmLoading} |
| | | onClick={() => { |
| | | emit('ok'); |
| | | }} |
| | | {...okButtonProps} |
| | | loading={confirmLoading} |
| | | > |
| | | {() => okText} |
| | | </Button> |
| | |
| | | {() => ( |
| | | <> |
| | | {props.showDetailBack && ( |
| | | <Col class="mx-2"> |
| | | {() => ( |
| | | <Button size="small" type="link" onClick={onClose}> |
| | | {() => <LeftOutlined />} |
| | | </Button> |
| | | )} |
| | | </Col> |
| | | <Button size="small" type="link" onClick={onClose}> |
| | | {() => <LeftOutlined />} |
| | | </Button> |
| | | )} |
| | | |
| | | {title && ( |
| | |
| | | export interface DrawerInstance { |
| | | setDrawerProps: (props: Partial<DrawerProps> | boolean) => void; |
| | | } |
| | | |
| | | export interface ReturnMethods extends DrawerInstance { |
| | | openDrawer: (visible?: boolean) => void; |
| | | transferDrawerData: (data: any) => void; |
| | | } |
| | | |
| | | export type RegisterFn = (drawerInstance: DrawerInstance, uuid?: string) => void; |
| | | |
| | | export interface ReturnInnerMethods extends DrawerInstance { |
| | |
| | | } |
| | | |
| | | export type UseDrawerReturnType = [RegisterFn, ReturnMethods]; |
| | | |
| | | export type UseDrawerInnerReturnType = [RegisterFn, ReturnInnerMethods]; |
| | | |
| | | export interface DrawerFooterProps { |
| | |
| | | DrawerProps, |
| | | UseDrawerInnerReturnType, |
| | | } from './types'; |
| | | import { ref, getCurrentInstance, onUnmounted, unref, reactive, computed } from 'vue'; |
| | | |
| | | import { ref, getCurrentInstance, onUnmounted, unref, reactive, computed, watchEffect } from 'vue'; |
| | | |
| | | import { isProdMode } from '/@/utils/env'; |
| | | import { isFunction } from '/@/utils/is'; |
| | | |
| | | const dataTransferRef = reactive<any>({}); |
| | | /** |
| | |
| | | drawerRef.value = drawerInstance; |
| | | loadedRef.value = true; |
| | | } |
| | | |
| | | const getInstance = () => { |
| | | const instance = unref(drawerRef); |
| | | if (!instance) { |
| | |
| | | } |
| | | return instance; |
| | | }; |
| | | |
| | | const methods: ReturnMethods = { |
| | | setDrawerProps: (props: Partial<DrawerProps>): void => { |
| | | getInstance().setDrawerProps(props); |
| | | }, |
| | | |
| | | openDrawer: (visible = true): void => { |
| | | getInstance().setDrawerProps({ |
| | | visible: visible, |
| | | }); |
| | | }, |
| | | |
| | | transferDrawerData(val: any) { |
| | | dataTransferRef[unref(uidRef)] = val; |
| | | }, |
| | |
| | | |
| | | return [getDrawer, methods]; |
| | | } |
| | | export const useDrawerInner = (): UseDrawerInnerReturnType => { |
| | | export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => { |
| | | const drawerInstanceRef = ref<DrawerInstance | null>(null); |
| | | const currentInstall = getCurrentInstance(); |
| | | const uidRef = ref<string>(''); |
| | |
| | | if (!currentInstall) { |
| | | throw new Error('instance is undefined!'); |
| | | } |
| | | |
| | | const getInstance = () => { |
| | | const instance = unref(drawerInstanceRef); |
| | | if (!instance) { |
| | |
| | | } |
| | | return instance; |
| | | }; |
| | | |
| | | const register = (modalInstance: DrawerInstance, uuid: string) => { |
| | | uidRef.value = uuid; |
| | | drawerInstanceRef.value = modalInstance; |
| | | currentInstall.emit('register', modalInstance); |
| | | }; |
| | | |
| | | watchEffect(() => { |
| | | const data = dataTransferRef[unref(uidRef)]; |
| | | if (!data) return; |
| | | if (!callbackFn || !isFunction(callbackFn)) return; |
| | | callbackFn(data); |
| | | }); |
| | | |
| | | return [ |
| | | register, |
| | | { |
| | | receiveDrawerDataRef: computed(() => { |
| | | return dataTransferRef[unref(uidRef)]; |
| | | }), |
| | | |
| | | changeLoading: (loading = true) => { |
| | | getInstance().setDrawerProps({ loading }); |
| | | }, |
| | | |
| | | changeOkLoading: (loading = true) => { |
| | | getInstance().setDrawerProps({ confirmLoading: loading }); |
| | | }, |
| | | |
| | | closeDrawer: () => { |
| | | getInstance().setDrawerProps({ visible: false }); |
| | | }, |
| | | |
| | | setDrawerProps: (props: Partial<DrawerProps>) => { |
| | | getInstance().setDrawerProps(props); |
| | | }, |
| | |
| | | <template> |
| | | <BasicDrawer v-bind="$attrs" @register="register" title="Drawer Title" width="50%"> |
| | | <p class="h-20">外部传递数据: {{ receiveDrawerDataRef }}</p> |
| | | <div :style="{ background: '#fff' }"> |
| | | <p class="h-20">外部传递数据: {{ receiveDrawerDataRef }}</p> |
| | | <BasicForm @register="registerForm" /> |
| | | </div> |
| | | </BasicDrawer> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | import { defineComponent, nextTick } from 'vue'; |
| | | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
| | | |
| | | import { BasicForm, FormSchema, useForm } from '/@/components/Form/index'; |
| | | const schemas: FormSchema[] = [ |
| | | { |
| | | field: 'field1', |
| | | component: 'Input', |
| | | label: '字段1', |
| | | colProps: { |
| | | span: 12, |
| | | }, |
| | | defaultValue: '111', |
| | | }, |
| | | { |
| | | field: 'field2', |
| | | component: 'Input', |
| | | label: '字段2', |
| | | colProps: { |
| | | span: 12, |
| | | }, |
| | | }, |
| | | ]; |
| | | export default defineComponent({ |
| | | components: { BasicDrawer }, |
| | | components: { BasicDrawer, BasicForm }, |
| | | setup() { |
| | | const [register, { receiveDrawerDataRef }] = useDrawerInner(); |
| | | return { register, receiveDrawerDataRef }; |
| | | const [registerForm, { setFieldsValue }] = useForm({ |
| | | labelWidth: 120, |
| | | schemas, |
| | | showActionButtonGroup: false, |
| | | actionColOptions: { |
| | | span: 24, |
| | | }, |
| | | }); |
| | | const [register, { receiveDrawerDataRef }] = useDrawerInner((data) => { |
| | | nextTick(() => { |
| | | // 方式1 |
| | | setFieldsValue({ |
| | | field2: data.data, |
| | | field1: data.info, |
| | | }); |
| | | }); |
| | | }); |
| | | return { register, receiveDrawerDataRef, schemas, registerForm }; |
| | | }, |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="px-10"> |
| | | <Alert message="使用 useDrawer 进行抽屉操作" show-icon class="my-4" /> |
| | | <a-button type="primary" class="mr-2" @click="openDrawerLoading">打开Drawer</a-button> |
| | | <div class="px-10 py-4"> |
| | | <Alert message="使用 useDrawer 进行抽屉操作" show-icon /> |
| | | <a-button type="primary" class="my-4" @click="openDrawerLoading">打开Drawer</a-button> |
| | | |
| | | <Alert message="内外同时同时显示隐藏" show-icon class="my-4" /> |
| | | <a-button type="primary" class="mr-2" @click="openDrawer2">打开Drawer</a-button> |
| | | <Alert message="自适应高度/显示footer" show-icon class="my-4" /> |
| | | <a-button type="primary" class="mr-2" @click="openDrawer3">打开Drawer</a-button> |
| | | <Alert message="内外同时同时显示隐藏" show-icon /> |
| | | <a-button type="primary" class="my-4" @click="openDrawer2">打开Drawer</a-button> |
| | | <Alert message="自适应高度/显示footer" show-icon /> |
| | | <a-button type="primary" class="my-4" @click="openDrawer3">打开Drawer</a-button> |
| | | |
| | | <Alert |
| | | message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式" |
| | | show-icon |
| | | class="my-4" |
| | | /> |
| | | <a-button type="primary" class="mr-2" @click="send">打开Drawer并传递数据</a-button> |
| | | <Alert message="详情页模式" show-icon class="my-4" /> |
| | | <a-button type="primary" class="mr-2" @click="openDrawer5">打开详情Drawer</a-button> |
| | | <a-button type="primary" class="my-4" @click="send">打开Drawer并传递数据</a-button> |
| | | <Alert message="详情页模式" show-icon /> |
| | | <a-button type="primary" class="my-4" @click="openDrawer5">打开详情Drawer</a-button> |
| | | <Drawer1 @register="register1" /> |
| | | <Drawer2 @register="register2" /> |
| | | <Drawer3 @register="register3" /> |
| | |
| | | <template> |
| | | <div class="px-10"> |
| | | <div class="px-10 py-4"> |
| | | <Alert |
| | | message="使用 useModal 进行弹窗操作,默认可以拖动,可以通过 draggable |
| | | 参数进行控制是否可以拖动/全屏" |
| | | show-icon |
| | | class="my-4" |
| | | /> |
| | | <a-button type="primary" class="mr-2" @click="openModalLoading" |
| | | <a-button type="primary" class="my-4" @click="openModalLoading" |
| | | >打开弹窗 默认可以拖动/全屏</a-button |
| | | > |
| | | |
| | | <Alert message="内外同时同时显示隐藏" show-icon class="my-4" /> |
| | | <a-button type="primary" class="mr-2" @click="openModal2">打开弹窗</a-button> |
| | | <Alert message="自适应高度" show-icon class="my-4" /> |
| | | <a-button type="primary" class="mr-2" @click="openModal3">打开弹窗</a-button> |
| | | <Alert message="内外同时同时显示隐藏" show-icon /> |
| | | <a-button type="primary" class="my-4" @click="openModal2">打开弹窗</a-button> |
| | | <Alert message="自适应高度" show-icon /> |
| | | <a-button type="primary" class="my-4" @click="openModal3">打开弹窗</a-button> |
| | | |
| | | <Alert |
| | | message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式" |
| | | show-icon |
| | | class="my-4" |
| | | /> |
| | | <a-button type="primary" class="mr-2" @click="send">打开弹窗并传递数据</a-button> |
| | | <a-button type="primary" class="my-4" @click="send">打开弹窗并传递数据</a-button> |
| | | |
| | | <Modal1 @register="register1" /> |
| | | <Modal2 @register="register2" /> |