Commit 1c1755cf5b4ada7263c05ddf4105abb52a2abb2f

Authored by Vben
1 parent 639520ad

fix(modal): ensure that the full screen height is calculated correctly

CHANGELOG.zh_CN.md
... ... @@ -2,9 +2,15 @@
2 2  
3 3 ### ✨ Features
4 4  
5   -- `Cropper` 头像裁剪新增圆形裁剪功能
6   -- 新增头像上传组件
7   -- `useDrawer`新增`closeDrawer`函数
  5 +- **CropperImage** `Cropper` 头像裁剪新增圆形裁剪功能
  6 +- **CropperAvatar** 新增头像上传组件
  7 +- **Drawer** `useDrawer`新增`closeDrawer`函数
  8 +
  9 +### 🐛 Bug Fixes
  10 +
  11 +- **Modal** 修复全屏高度计算错误
  12 +- **PageWrapper** 修复高度计算问题
  13 +- 修复后台模式下,Iframe 路由错误
8 14  
9 15 ## 2.4.2(2021-06-10)
10 16  
... ...
src/components/Drawer/src/BasicDrawer.vue
... ... @@ -163,7 +163,7 @@
163 163  
164 164 function setDrawerProps(props: Partial<DrawerProps>): void {
165 165 // Keep the last setDrawerProps
166   - propsRef.value = deepMerge((unref(propsRef) as any) || {}, props);
  166 + propsRef.value = deepMerge(unref(propsRef), props);
167 167  
168 168 if (Reflect.has(props, 'visible')) {
169 169 visibleRef.value = !!props.visible;
... ...
src/components/Drawer/src/useDrawer.ts
... ... @@ -5,7 +5,6 @@ import type {
5 5 DrawerProps,
6 6 UseDrawerInnerReturnType,
7 7 } from './typing';
8   -
9 8 import {
10 9 ref,
11 10 getCurrentInstance,
... ... @@ -16,11 +15,9 @@ import {
16 15 toRaw,
17 16 computed,
18 17 } from 'vue';
19   -
20 18 import { isProdMode } from '/@/utils/env';
21 19 import { isFunction } from '/@/utils/is';
22 20 import { tryOnUnmounted } from '@vueuse/core';
23   -
24 21 import { isEqual } from 'lodash-es';
25 22 import { error } from '/@/utils/log';
26 23  
... ...
src/components/Modal/index.ts
  1 +import { withInstall } from '/@/utils';
1 2 import './src/index.less';
2   -import BasicModal from './src/BasicModal.vue';
  3 +import basicModal from './src/BasicModal.vue';
3 4  
4   -export { BasicModal };
  5 +export const BasicModal = withInstall(basicModal);
5 6 export { useModalContext } from './src/hooks/useModalContext';
6 7 export { useModal, useModalInner } from './src/hooks/useModal';
7   -export * from './src/types';
  8 +export * from './src/typing';
... ...
src/components/Modal/src/BasicModal.vue
... ... @@ -49,7 +49,7 @@
49 49 </Modal>
50 50 </template>
51 51 <script lang="ts">
52   - import type { ModalProps, ModalMethods } from './types';
  52 + import type { ModalProps, ModalMethods } from './typing';
53 53  
54 54 import {
55 55 defineComponent,
... ... @@ -62,20 +62,17 @@
62 62 getCurrentInstance,
63 63 nextTick,
64 64 } from 'vue';
65   -
66 65 import Modal from './components/Modal';
67 66 import ModalWrapper from './components/ModalWrapper.vue';
68 67 import ModalClose from './components/ModalClose.vue';
69 68 import ModalFooter from './components/ModalFooter.vue';
70 69 import ModalHeader from './components/ModalHeader.vue';
71   -
72 70 import { isFunction } from '/@/utils/is';
73 71 import { deepMerge } from '/@/utils';
74   -
75 72 import { basicProps } from './props';
76 73 import { useFullScreen } from './hooks/useModalFullScreen';
77   -
78 74 import { omit } from 'lodash-es';
  75 +
79 76 export default defineComponent({
80 77 name: 'BasicModal',
81 78 components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
... ... @@ -189,7 +186,7 @@
189 186 */
190 187 function setModalProps(props: Partial<ModalProps>): void {
191 188 // Keep the last setModalProps
192   - propsRef.value = deepMerge(unref(propsRef) || {}, props);
  189 + propsRef.value = deepMerge(unref(propsRef), props);
193 190 if (!Reflect.has(props, 'visible')) return;
194 191 visibleRef.value = !!props.visible;
195 192 }
... ...
src/components/Modal/src/components/Modal.tsx
... ... @@ -20,7 +20,6 @@ export default defineComponent({
20 20  
21 21 return () => {
22 22 const propsData = { ...unref(attrs), ...props } as Recordable;
23   -
24 23 return <Modal {...propsData}>{extendSlots(slots)}</Modal>;
25 24 };
26 25 },
... ...
src/components/Modal/src/components/ModalClose.vue
... ... @@ -2,7 +2,6 @@
2 2 <div :class="getClass">
3 3 <template v-if="canFullscreen">
4 4 <FullscreenExitOutlined role="full" @click="handleFullScreen" v-if="fullScreen" />
5   -
6 5 <FullscreenOutlined role="close" @click="handleFullScreen" v-else />
7 6 </template>
8 7 <CloseOutlined @click="handleCancel" />
... ... @@ -12,14 +11,13 @@
12 11 import { defineComponent, computed } from 'vue';
13 12 import { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined } from '@ant-design/icons-vue';
14 13 import { useDesign } from '/@/hooks/web/useDesign';
15   - import { propTypes } from '/@/utils/propTypes';
16 14  
17 15 export default defineComponent({
18 16 name: 'ModalClose',
19 17 components: { FullscreenExitOutlined, FullscreenOutlined, CloseOutlined },
20 18 props: {
21   - canFullscreen: propTypes.bool.def(true),
22   - fullScreen: propTypes.bool,
  19 + canFullscreen: { type: Boolean, default: true },
  20 + fullScreen: { type: Boolean },
23 21 },
24 22 emits: ['cancel', 'fullscreen'],
25 23 setup(props, { emit }) {
... ... @@ -38,6 +36,7 @@
38 36 function handleCancel(e: Event) {
39 37 emit('cancel', e);
40 38 }
  39 +
41 40 function handleFullScreen(e: Event) {
42 41 e?.stopPropagation();
43 42 e?.preventDefault();
... ...
src/components/Modal/src/components/ModalFooter.vue
... ... @@ -33,6 +33,7 @@
33 33 function handleCancel(e: Event) {
34 34 emit('cancel', e);
35 35 }
  36 +
36 37 return { handleOk, handleCancel };
37 38 },
38 39 });
... ...
src/components/Modal/src/components/ModalHeader.vue
... ... @@ -8,7 +8,6 @@
8 8 import { defineComponent } from 'vue';
9 9 import { BasicTitle } from '/@/components/Basic';
10 10  
11   - import { propTypes } from '/@/utils/propTypes';
12 11 export default defineComponent({
13 12 name: 'BasicModalHeader',
14 13 components: { BasicTitle },
... ... @@ -16,7 +15,7 @@
16 15 helpMessage: {
17 16 type: [String, Array] as PropType<string | string[]>,
18 17 },
19   - title: propTypes.string,
  18 + title: { type: String },
20 19 },
21 20 });
22 21 </script>
... ...
src/components/Modal/src/components/ModalWrapper.vue
... ... @@ -6,9 +6,7 @@
6 6 </ScrollContainer>
7 7 </template>
8 8 <script lang="ts">
9   - import type { ModalWrapperProps } from '../types';
10 9 import type { CSSProperties } from 'vue';
11   -
12 10 import {
13 11 defineComponent,
14 12 computed,
... ... @@ -20,31 +18,31 @@
20 18 nextTick,
21 19 onUnmounted,
22 20 } from 'vue';
23   -
24 21 import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
25 22 import { ScrollContainer } from '/@/components/Container';
26   -
27   - import { propTypes } from '/@/utils/propTypes';
28 23 import { createModalContext } from '../hooks/useModalContext';
  24 + import { useMutationObserver } from '@vueuse/core';
  25 +
  26 + const props = {
  27 + loading: { type: Boolean },
  28 + useWrapper: { type: Boolean, default: true },
  29 + modalHeaderHeight: { type: Number, default: 57 },
  30 + modalFooterHeight: { type: Number, default: 74 },
  31 + minHeight: { type: Number, default: 200 },
  32 + height: { type: Number },
  33 + footerOffset: { type: Number, default: 0 },
  34 + visible: { type: Boolean },
  35 + fullScreen: { type: Boolean },
  36 + loadingTip: { type: String },
  37 + };
29 38  
30 39 export default defineComponent({
31 40 name: 'ModalWrapper',
32 41 components: { ScrollContainer },
33 42 inheritAttrs: false,
34   - props: {
35   - loading: propTypes.bool,
36   - useWrapper: propTypes.bool.def(true),
37   - modalHeaderHeight: propTypes.number.def(57),
38   - modalFooterHeight: propTypes.number.def(74),
39   - minHeight: propTypes.number.def(200),
40   - height: propTypes.number,
41   - footerOffset: propTypes.number.def(0),
42   - visible: propTypes.bool,
43   - fullScreen: propTypes.bool,
44   - loadingTip: propTypes.string,
45   - },
  43 + props,
46 44 emits: ['height-change', 'ext-height'],
47   - setup(props: ModalWrapperProps, { emit }) {
  45 + setup(props, { emit }) {
48 46 const wrapperRef = ref<ComponentRef>(null);
49 47 const spinRef = ref<ElRef>(null);
50 48 const realHeightRef = ref(0);
... ... @@ -56,6 +54,17 @@
56 54  
57 55 useWindowSizeFn(setModalHeight.bind(null, false));
58 56  
  57 + useMutationObserver(
  58 + spinRef,
  59 + () => {
  60 + setModalHeight();
  61 + },
  62 + {
  63 + attributes: true,
  64 + subtree: true,
  65 + }
  66 + );
  67 +
59 68 createModalContext({
60 69 redoModalHeight: setModalHeight,
61 70 });
... ... @@ -63,8 +72,7 @@
63 72 const spinStyle = computed((): CSSProperties => {
64 73 return {
65 74 minHeight: `${props.minHeight}px`,
66   - // padding 28
67   - maxHeight: `${unref(realHeightRef)}px`,
  75 + [props.fullScreen ? 'height' : 'maxHeight']: `${unref(realHeightRef)}px`,
68 76 };
69 77 });
70 78  
... ... @@ -87,7 +95,6 @@
87 95 onMounted(() => {
88 96 const { modalHeaderHeight, modalFooterHeight } = props;
89 97 emit('ext-height', modalHeaderHeight + modalFooterHeight);
90   - // listenElResize();
91 98 });
92 99  
93 100 onUnmounted(() => {
... ...
src/components/Modal/src/hooks/useModal.ts
... ... @@ -4,8 +4,7 @@ import type {
4 4 ModalProps,
5 5 ReturnMethods,
6 6 UseModalInnerReturnType,
7   -} from '../types';
8   -
  7 +} from '../typing';
9 8 import {
10 9 ref,
11 10 onUnmounted,
... ... @@ -20,10 +19,10 @@ import { isProdMode } from &#39;/@/utils/env&#39;;
20 19 import { isFunction } from '/@/utils/is';
21 20 import { isEqual } from 'lodash-es';
22 21 import { tryOnUnmounted } from '@vueuse/core';
23   -
24 22 import { error } from '/@/utils/log';
25 23 import { computed } from 'vue';
26   -const dataTransferRef = reactive<any>({});
  24 +
  25 +const dataTransfer = reactive<any>({});
27 26  
28 27 const visibleData = reactive<{ [key: number]: boolean }>({});
29 28  
... ... @@ -31,29 +30,31 @@ const visibleData = reactive&lt;{ [key: number]: boolean }&gt;({});
31 30 * @description: Applicable to independent modal and call outside
32 31 */
33 32 export function useModal(): UseModalReturnType {
34   - const modalRef = ref<Nullable<ModalMethods>>(null);
35   - const loadedRef = ref<Nullable<boolean>>(false);
36   - const uidRef = ref<string>('');
  33 + const modal = ref<Nullable<ModalMethods>>(null);
  34 + const loaded = ref<Nullable<boolean>>(false);
  35 + const uid = ref<string>('');
37 36  
38 37 function register(modalMethod: ModalMethods, uuid: string) {
39   - uidRef.value = uuid;
40   -
  38 + if (!getCurrentInstance()) {
  39 + throw new Error('useModal() can only be used inside setup() or functional components!');
  40 + }
  41 + uid.value = uuid;
41 42 isProdMode() &&
42 43 onUnmounted(() => {
43   - modalRef.value = null;
44   - loadedRef.value = false;
45   - dataTransferRef[unref(uidRef)] = null;
  44 + modal.value = null;
  45 + loaded.value = false;
  46 + dataTransfer[unref(uid)] = null;
46 47 });
47   - if (unref(loadedRef) && isProdMode() && modalMethod === unref(modalRef)) return;
  48 + if (unref(loaded) && isProdMode() && modalMethod === unref(modal)) return;
48 49  
49   - modalRef.value = modalMethod;
  50 + modal.value = modalMethod;
50 51 modalMethod.emitVisible = (visible: boolean, uid: number) => {
51 52 visibleData[uid] = visible;
52 53 };
53 54 }
54 55  
55 56 const getInstance = () => {
56   - const instance = unref(modalRef);
  57 + const instance = unref(modal);
57 58 if (!instance) {
58 59 error('useModal instance is undefined!');
59 60 }
... ... @@ -66,7 +67,7 @@ export function useModal(): UseModalReturnType {
66 67 },
67 68  
68 69 getVisible: computed((): boolean => {
69   - return visibleData[~~unref(uidRef)];
  70 + return visibleData[~~unref(uid)];
70 71 }),
71 72  
72 73 redoModalHeight: () => {
... ... @@ -79,15 +80,15 @@ export function useModal(): UseModalReturnType {
79 80 });
80 81  
81 82 if (!data) return;
82   -
  83 + const id = unref(uid);
83 84 if (openOnSet) {
84   - dataTransferRef[unref(uidRef)] = null;
85   - dataTransferRef[unref(uidRef)] = toRaw(data);
  85 + dataTransfer[id] = null;
  86 + dataTransfer[id] = toRaw(data);
86 87 return;
87 88 }
88   - const equal = isEqual(toRaw(dataTransferRef[unref(uidRef)]), toRaw(data));
  89 + const equal = isEqual(toRaw(dataTransfer[id]), toRaw(data));
89 90 if (!equal) {
90   - dataTransferRef[unref(uidRef)] = toRaw(data);
  91 + dataTransfer[id] = toRaw(data);
91 92 }
92 93 },
93 94  
... ... @@ -103,9 +104,6 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType =&gt; {
103 104 const currentInstance = getCurrentInstance();
104 105 const uidRef = ref<string>('');
105 106  
106   - // currentInstall.type.emits = [...currentInstall.type.emits, 'register'];
107   - // Object.assign(currentInstall.type.emits, ['register']);
108   -
109 107 const getInstance = () => {
110 108 const instance = unref(modalInstanceRef);
111 109 if (!instance) {
... ... @@ -125,7 +123,7 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType =&gt; {
125 123 };
126 124  
127 125 watchEffect(() => {
128   - const data = dataTransferRef[unref(uidRef)];
  126 + const data = dataTransfer[unref(uidRef)];
129 127 if (!data) return;
130 128 if (!callbackFn || !isFunction(callbackFn)) return;
131 129 nextTick(() => {
... ...
src/components/Modal/src/hooks/useModalFullScreen.ts
... ... @@ -12,7 +12,6 @@ export function useFullScreen(context: UseFullScreenContext) {
12 12  
13 13 const getWrapClassName = computed(() => {
14 14 const clsName = unref(context.wrapClassName) || '';
15   -
16 15 return unref(fullScreenRef) ? `fullscreen-modal ${clsName} ` : unref(clsName);
17 16 });
18 17  
... ...
src/components/Modal/src/props.ts
1 1 import type { PropType, CSSProperties } from 'vue';
  2 +import type { ModalWrapperProps } from './typing';
2 3 import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes';
3   -
4 4 import { useI18n } from '/@/hooks/web/useI18n';
5   -import { propTypes, VueNode } from '/@/utils/propTypes';
6   -import type { ModalWrapperProps } from './types';
  5 +
7 6 const { t } = useI18n();
8 7  
9 8 export const modalProps = {
10   - visible: propTypes.bool,
11   - scrollTop: propTypes.bool.def(true),
12   - height: propTypes.number,
13   - minHeight: propTypes.number,
  9 + visible: { type: Boolean },
  10 + scrollTop: { type: Boolean, default: true },
  11 + height: { type: Number },
  12 + minHeight: { type: Number },
14 13 // open drag
15   - draggable: propTypes.bool.def(true),
16   - centered: propTypes.bool,
17   - cancelText: propTypes.string.def(t('common.cancelText')),
18   - okText: propTypes.string.def(t('common.okText')),
  14 + draggable: { type: Boolean, default: true },
  15 + centered: { type: Boolean },
  16 + cancelText: { type: String, default: t('common.cancelText') },
  17 + okText: { type: String, default: t('common.okText') },
19 18  
20 19 closeFunc: Function as PropType<() => Promise<boolean>>,
21 20 };
22 21  
23 22 export const basicProps = Object.assign({}, modalProps, {
24   - defaultFullscreen: propTypes.bool,
  23 + defaultFullscreen: { type: Boolean },
25 24 // Can it be full screen
26   - canFullscreen: propTypes.bool.def(true),
  25 + canFullscreen: { type: Boolean, default: true },
27 26 // After enabling the wrapper, the bottom can be increased in height
28   - wrapperFooterOffset: propTypes.number.def(0),
  27 + wrapperFooterOffset: { type: Number, default: 0 },
29 28 // Warm reminder message
30 29 helpMessage: [String, Array] as PropType<string | string[]>,
31 30 // Whether to setting wrapper
32   - useWrapper: propTypes.bool.def(true),
33   - loading: propTypes.bool,
34   - loadingTip: propTypes.string,
  31 + useWrapper: { type: Boolean, default: true },
  32 + loading: { type: Boolean },
  33 + loadingTip: { type: String },
35 34 /**
36 35 * @description: Show close button
37 36 */
38   - showCancelBtn: propTypes.bool.def(true),
  37 + showCancelBtn: { type: Boolean, default: true },
39 38 /**
40 39 * @description: Show confirmation button
41 40 */
42   - showOkBtn: propTypes.bool.def(true),
  41 + showOkBtn: { type: Boolean, default: true },
43 42  
44 43 wrapperProps: Object as PropType<Partial<ModalWrapperProps>>,
45 44  
... ... @@ -47,38 +46,38 @@ export const basicProps = Object.assign({}, modalProps, {
47 46  
48 47 bodyStyle: Object as PropType<CSSProperties>,
49 48  
50   - closable: propTypes.bool.def(true),
  49 + closable: { type: Boolean, default: true },
51 50  
52 51 closeIcon: Object as PropType<VueNode>,
53 52  
54   - confirmLoading: propTypes.bool,
  53 + confirmLoading: { type: Boolean },
55 54  
56   - destroyOnClose: propTypes.bool,
  55 + destroyOnClose: { type: Boolean },
57 56  
58 57 footer: Object as PropType<VueNode>,
59 58  
60 59 getContainer: Function as PropType<() => any>,
61 60  
62   - mask: propTypes.bool.def(true),
  61 + mask: { type: Boolean, default: true },
63 62  
64   - maskClosable: propTypes.bool.def(true),
65   - keyboard: propTypes.bool.def(true),
  63 + maskClosable: { type: Boolean, default: true },
  64 + keyboard: { type: Boolean, default: true },
66 65  
67 66 maskStyle: Object as PropType<CSSProperties>,
68 67  
69   - okType: propTypes.string.def('primary'),
  68 + okType: { type: String, default: 'primary' },
70 69  
71 70 okButtonProps: Object as PropType<ButtonProps>,
72 71  
73 72 cancelButtonProps: Object as PropType<ButtonProps>,
74 73  
75   - title: propTypes.string,
  74 + title: { type: String },
76 75  
77   - visible: propTypes.bool,
  76 + visible: { type: Boolean },
78 77  
79 78 width: [String, Number] as PropType<string | number>,
80 79  
81   - wrapClassName: propTypes.string,
  80 + wrapClassName: { type: String },
82 81  
83   - zIndex: propTypes.number,
  82 + zIndex: { type: Number },
84 83 });
... ...
src/components/Modal/src/types.ts renamed to src/components/Modal/src/typing.ts
src/components/Qrcode/index.ts
1   -export { default as QrCode } from './src/Qrcode.vue';
  1 +import { withInstall } from '/@/utils';
  2 +import qrCode from './src/Qrcode.vue';
2 3  
3   -export * from './src/types';
  4 +export const QrCode = withInstall(qrCode);
  5 +export * from './src/typing';
... ...
src/components/Qrcode/src/Qrcode.vue
... ... @@ -8,7 +8,7 @@
8 8 import { toCanvas, QRCodeRenderersOptions, LogoType } from './qrcodePlus';
9 9 import { toDataURL } from 'qrcode';
10 10 import { downloadByUrl } from '/@/utils/file/download';
11   - import { QrcodeDoneEventParams } from './types';
  11 + import { QrcodeDoneEventParams } from './typing';
12 12  
13 13 export default defineComponent({
14 14 name: 'QrCode',
... ...
src/components/Qrcode/src/drawCanvas.ts
1 1 import { toCanvas } from 'qrcode';
2 2 import type { QRCodeRenderersOptions } from 'qrcode';
3   -import { RenderQrCodeParams, ContentType } from './types';
  3 +import { RenderQrCodeParams, ContentType } from './typing';
4 4 export const renderQrCode = ({ canvas, content, width = 0, options = {} }: RenderQrCodeParams) => {
5 5 // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率
6 6 options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content);
... ...
src/components/Qrcode/src/drawLogo.ts
1 1 import { isString } from '/@/utils/is';
2   -import { RenderQrCodeParams, LogoType } from './types';
  2 +import { RenderQrCodeParams, LogoType } from './typing';
3 3 export const drawLogo = ({ canvas, logo }: RenderQrCodeParams) => {
4 4 if (!logo) {
5 5 return new Promise((resolve) => {
6 6 resolve((canvas as HTMLCanvasElement).toDataURL());
7 7 });
8 8 }
9   -
10 9 const canvasWidth = (canvas as HTMLCanvasElement).width;
11 10 const {
12 11 logoSize = 0.15,
... ...
src/components/Qrcode/src/qrcodePlus.ts
1 1 // 参考 qr-code-with-logo 进行ts版本修改
2 2 import { toCanvas } from './toCanvas';
3   -export * from './types';
4   -
  3 +export * from './typing';
5 4 export { toCanvas };
... ...
src/components/Qrcode/src/toCanvas.ts
1 1 import { renderQrCode } from './drawCanvas';
2 2 import { drawLogo } from './drawLogo';
3   -import { RenderQrCodeParams } from './types';
  3 +import { RenderQrCodeParams } from './typing';
4 4 export const toCanvas = (options: RenderQrCodeParams) => {
5 5 return renderQrCode(options)
6 6 .then(() => {
... ...
src/components/Qrcode/src/types.ts renamed to src/components/Qrcode/src/typing.ts
src/layouts/default/header/components/lock/LockModal.vue
... ... @@ -95,7 +95,7 @@
95 95 &__entry {
96 96 position: relative;
97 97 //height: 240px;
98   - padding: 130px 30px 60px 30px;
  98 + padding: 130px 30px 30px 30px;
99 99 border-radius: 10px;
100 100 }
101 101  
... ...
src/views/demo/comp/drawer/index.vue
... ... @@ -8,10 +8,7 @@
8 8 <Alert message="自适应高度/显示footer" show-icon />
9 9 <a-button type="primary" class="my-4" @click="openDrawer3(true)"> 打开Drawer </a-button>
10 10  
11   - <Alert
12   - message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式"
13   - show-icon
14   - />
  11 + <Alert message="内外数据交互" show-icon />
15 12 <a-button type="primary" class="my-4" @click="send"> 打开Drawer并传递数据 </a-button>
16 13 <Alert message="详情页模式" show-icon />
17 14 <a-button type="primary" class="my-4" @click="openDrawer5(true)"> 打开详情Drawer </a-button>
... ...
src/views/demo/comp/modal/index.vue
... ... @@ -14,10 +14,7 @@
14 14 <Alert message="自适应高度" show-icon />
15 15 <a-button type="primary" class="my-4" @click="openModal3"> 打开弹窗 </a-button>
16 16  
17   - <Alert
18   - message="内外数据交互,外部通过 transferModalData 发送,内部通过 receiveDrawerDataRef 接收。该数据具有响应式"
19   - show-icon
20   - />
  17 + <Alert message="内外数据交互" show-icon />
21 18 <a-button type="primary" class="my-4" @click="send"> 打开弹窗并传递数据 </a-button>
22 19  
23 20 <Modal1 @register="register1" :minHeight="100" />
... ...
types/global.d.ts
1 1 import type {
2 2 ComponentRenderProxy,
3 3 VNode,
  4 + VNodeChild,
4 5 ComponentPublicInstance,
5 6 FunctionalComponent,
6 7 PropType as VuePropType,
... ... @@ -23,6 +24,7 @@ declare global {
23 24  
24 25 // vue
25 26 declare type PropType<T> = VuePropType<T>;
  27 + declare type VueNode = VNodeChild | JSX.Element;
26 28  
27 29 export type Writable<T> = {
28 30 -readonly [P in keyof T]: T[P];
... ...