diff --git a/packages/devui-vue/devui/drawer/index.ts b/packages/devui-vue/devui/drawer/index.ts index 0c923f4da8..c0ac81fb9b 100644 --- a/packages/devui-vue/devui/drawer/index.ts +++ b/packages/devui-vue/devui/drawer/index.ts @@ -8,10 +8,16 @@ Drawer.install = function(app: App): void { export { Drawer, DrawerService } +// TODO: no-service model exists memory leak +// rest tasks +// 1. draggable width +// 2. function of the 1st icon in header-component +// 3. rest service-model api +// 4. typescript type of props export default { title: 'Drawer 抽屉板', category: '反馈', - status: '60%', + status: '75%', install(app: App): void { app.use(Drawer as any) app.config.globalProperties.$drawerService = DrawerService diff --git a/packages/devui-vue/devui/drawer/src/components/drawer-body.tsx b/packages/devui-vue/devui/drawer/src/components/drawer-body.tsx index a52965f7c0..d3525a420f 100644 --- a/packages/devui-vue/devui/drawer/src/components/drawer-body.tsx +++ b/packages/devui-vue/devui/drawer/src/components/drawer-body.tsx @@ -13,6 +13,7 @@ export default defineComponent({ const width: any = inject('width') const visible: boolean = inject('visible') const backdropCloseable: any = inject('backdropCloseable') + const destroyOnHide: any = inject('destroyOnHide') const navRight = computed(() => position.value === 'right' ? { 'right': 0 } : { 'left': 0 }) const navWidth = computed(() => isFullScreen.value ? '100vw' : width.value) @@ -35,18 +36,23 @@ export default defineComponent({ visible, clickContent, handleDrawerClose, + destroyOnHide, } }, render() { const { - zindex, slots, isCover, navRight, navWidth, visible, handleDrawerClose - } = this + zindex, slots, isCover, navRight, navWidth, + visible, handleDrawerClose, destroyOnHide } = this - if (!visible) return null + if (destroyOnHide.value && !visible) { + return null + } + + const visibleVal = visible ? 'visible' : 'hidden' return ( -
+
{isCover ?
: null}
diff --git a/packages/devui-vue/devui/drawer/src/components/drawer-container.tsx b/packages/devui-vue/devui/drawer/src/components/drawer-container.tsx index c45f3b2545..b52256240e 100644 --- a/packages/devui-vue/devui/drawer/src/components/drawer-container.tsx +++ b/packages/devui-vue/devui/drawer/src/components/drawer-container.tsx @@ -4,11 +4,16 @@ export default defineComponent({ name: 'DrawerContainer', setup() { const visible = inject('visible') - return { visible } + const destroyOnHide = inject('destroyOnHide') + return { visible, destroyOnHide } }, render() { - const { visible } = this - if (!visible) return null - return
内容区域
+ const { visible, destroyOnHide } = this + + if (destroyOnHide.value && !visible) { + return null + } + const visibleVal = this.visible ? 'visible' : 'hidden' + return
内容区域
} }) \ No newline at end of file diff --git a/packages/devui-vue/devui/drawer/src/components/drawer-header.tsx b/packages/devui-vue/devui/drawer/src/components/drawer-header.tsx index 7e3e3a05c0..13ed5062e0 100644 --- a/packages/devui-vue/devui/drawer/src/components/drawer-header.tsx +++ b/packages/devui-vue/devui/drawer/src/components/drawer-header.tsx @@ -3,12 +3,13 @@ import { defineComponent, ref, inject, computed } from 'vue' import './drawer-header.scss' export default defineComponent({ - name: 'DrawerHeader', // 头部 + name: 'DrawerHeader', emits: ['toggleFullScreen', 'close'], setup(props, ctx) { const isFullScreen = ref(false) - const visible: boolean = inject('visible') + const visible = inject('visible') + const destroyOnHide = inject('destroyOnHide') const fullScreenClassName = computed(() => isFullScreen.value ? 'icon icon-minimize' : 'icon icon-maxmize') @@ -22,15 +23,22 @@ export default defineComponent({ ctx.emit('close') } - return { fullScreenClassName, visible, handleFullScreen, handleDrawerClose, } + return { fullScreenClassName, visible, handleFullScreen, handleDrawerClose, destroyOnHide } }, render() { - const { handleFullScreen, handleDrawerClose, visible, fullScreenClassName } = this - - if (!visible) return null + const { + handleFullScreen, handleDrawerClose, visible, + fullScreenClassName, destroyOnHide + } = this + + if (destroyOnHide.value && !visible) { + return null + } + + const visibleVal = visible ? 'visible' : 'hidden' return ( -
+
diff --git a/packages/devui-vue/devui/drawer/src/drawer-service.tsx b/packages/devui-vue/devui/drawer/src/drawer-service.tsx index 645f62d74c..237a0fc8a6 100644 --- a/packages/devui-vue/devui/drawer/src/drawer-service.tsx +++ b/packages/devui-vue/devui/drawer/src/drawer-service.tsx @@ -14,7 +14,7 @@ function createDrawerApp(props: DrawerProps, drawer: drawerInstance, el: HTMLEle return drawer } const res = createApp( - {{ header: props.header, content: props.content }} + {{ header: props.header, content: props.content }} ) res.mount(el) return res @@ -39,8 +39,11 @@ class Drawer { } public show(): void { - this.div = document.createElement('div') - this.drawer = createDrawerApp(this.props, this.drawer, this.div) + if (!this.drawer) { + this.div = document.createElement('div') + this.drawer = createDrawerApp(this.props, this.drawer, this.div) + } + // TODO: this is a hack, need to find a better way. (the row 62) this.drawer._instance.props.visible = true } @@ -55,12 +58,15 @@ class Drawer { public hideDirectly = (): void => { this.drawer._instance.props.visible = false - this.div.remove() + // this.div.remove() } public destroy = (): void => { - this.drawer.unmount() - this.drawer = null - this.div.remove() + // when drawer is null, it has been destroyed already and no need to destroy again + if (this.drawer) { + this.drawer.unmount() + this.drawer = null + this.div.remove() + } } } diff --git a/packages/devui-vue/devui/drawer/src/drawer-types.ts b/packages/devui-vue/devui/drawer/src/drawer-types.ts index 3be23c4aea..149cc22cba 100644 --- a/packages/devui-vue/devui/drawer/src/drawer-types.ts +++ b/packages/devui-vue/devui/drawer/src/drawer-types.ts @@ -29,6 +29,10 @@ export const drawerProps = { type: Boolean, default: true, }, + destroyOnHide: { // 是否在隐藏时销毁 + type: Boolean, + default: false, + }, beforeHidden: { // 关闭前的回调 type: [Promise, Function] as PropType | (() => boolean | Promise)>, }, diff --git a/packages/devui-vue/devui/drawer/src/drawer.tsx b/packages/devui-vue/devui/drawer/src/drawer.tsx index 7e2d076dcd..9701947cfc 100644 --- a/packages/devui-vue/devui/drawer/src/drawer.tsx +++ b/packages/devui-vue/devui/drawer/src/drawer.tsx @@ -12,10 +12,10 @@ export default defineComponent({ setup(props: DrawerProps, { emit, slots }) { const { width, visible, zIndex, isCover, escKeyCloseable, position, - backdropCloseable, + backdropCloseable, destroyOnHide } = toRefs(props) const isFullScreen = ref(false) - + const fullscreen = () => { isFullScreen.value = !isFullScreen.value } @@ -28,7 +28,7 @@ export default defineComponent({ } if (result) return; - // BUG: 以服务方式 此处不生效 + // BUG: this is not working when use service model emit('update:visible', false) emit('close') } @@ -42,7 +42,10 @@ export default defineComponent({ watch(visible, (val) => { if (val) { emit('afterOpened') - isFullScreen.value = false + // TODO: destroy-model should reset props, this function should be extracted + if (destroyOnHide.value) { + isFullScreen.value = false + } } if (escKeyCloseable && val) { document.addEventListener('keyup', escCloseDrawer) @@ -51,6 +54,9 @@ export default defineComponent({ } }) + // TODO: need to handle these params again + // 1. should be provided by params' value (eg: provide('closeDrawer', closeDrawer.value)) + // 2. which param should be provided provide('closeDrawer', closeDrawer) provide('zindex', zIndex) provide('isCover', isCover) @@ -59,6 +65,7 @@ export default defineComponent({ provide('visible', visible) provide('isFullScreen', isFullScreen) provide('backdropCloseable', backdropCloseable) + provide('destroyOnHide', destroyOnHide) onUnmounted(() => { document.removeEventListener('keyup', escCloseDrawer) @@ -73,14 +80,15 @@ export default defineComponent({ } }, render() { - const fullscreen: any = this.fullscreen - const closeDrawer: any = this.closeDrawer - - if (!this.visible) return null + const { fullscreen, closeDrawer, visible, destroyOnHide } = this; + if (destroyOnHide.value && !visible) { + return null + } + const visibleVal = visible ? 'visible' : 'hidden' return ( - + {/* BUG: 已使用作用域插槽解决 此处对应的 DEMO 使用了 **双向绑定** 导致可以关闭【一种关闭了的'假象'】。*/} {this.slots.header ? this.slots.header({fullscreen, closeDrawer}) : diff --git a/packages/devui-vue/docs/components/drawer/index.md b/packages/devui-vue/docs/components/drawer/index.md index 1b6bf592d2..daee278cdb 100644 --- a/packages/devui-vue/docs/components/drawer/index.md +++ b/packages/devui-vue/docs/components/drawer/index.md @@ -16,12 +16,11 @@ ```vue