Skip to content

feat(drawer): add destroyOnHide prop #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/devui-vue/devui/drawer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 10 additions & 4 deletions packages/devui-vue/devui/drawer/src/components/drawer-body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 (
<div class="devui-drawer" style={{ zIndex: zindex }} onClick={handleDrawerClose} >
<div class="devui-drawer" style={{ zIndex: zindex, visibility : visibleVal }} onClick={handleDrawerClose} >
{isCover ? <div class="devui-overlay-backdrop" /> : null}
<div class="devui-overlay-wrapper">
<div class="devui-drawer-nav" style={{ 'width': navWidth, ...navRight }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <div>内容区域</div>
const { visible, destroyOnHide } = this

if (destroyOnHide.value && !visible) {
return null
}
const visibleVal = this.visible ? 'visible' : 'hidden'
return <div style={{ visibility : visibleVal }}>内容区域</div>
}
})
22 changes: 15 additions & 7 deletions packages/devui-vue/devui/drawer/src/components/drawer-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand All @@ -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 (
<div class="devui-drawer-header">
<div class="devui-drawer-header" style= {{ visibility : visibleVal }}>
<div class="devui-drawer-header-item">
<span class="devui-drawer-header-item icon icon-more-operate" />
</div>
Expand Down
20 changes: 13 additions & 7 deletions packages/devui-vue/devui/drawer/src/drawer-service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function createDrawerApp(props: DrawerProps, drawer: drawerInstance, el: HTMLEle
return drawer
}
const res = createApp(
<DDrawer {...props}>{{ header: props.header, content: props.content }}</DDrawer>
<DDrawer v-model:visible={props.visible}>{{ header: props.header, content: props.content }}</DDrawer>
)
res.mount(el)
return res
Expand All @@ -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
}

Expand All @@ -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()
}
}
}
4 changes: 4 additions & 0 deletions packages/devui-vue/devui/drawer/src/drawer-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export const drawerProps = {
type: Boolean,
default: true,
},
destroyOnHide: { // 是否在隐藏时销毁
type: Boolean,
default: false,
},
beforeHidden: { // 关闭前的回调
type: [Promise, Function] as PropType<Promise<boolean> | (() => boolean | Promise<boolean>)>,
},
Expand Down
26 changes: 17 additions & 9 deletions packages/devui-vue/devui/drawer/src/drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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')
}
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -59,6 +65,7 @@ export default defineComponent({
provide('visible', visible)
provide('isFullScreen', isFullScreen)
provide('backdropCloseable', backdropCloseable)
provide('destroyOnHide', destroyOnHide)

onUnmounted(() => {
document.removeEventListener('keyup', escCloseDrawer)
Expand All @@ -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 (
<Teleport to="body">
<DrawerBody>
<DrawerBody style= {{ visibility : visibleVal }}>
{/* BUG: 已使用作用域插槽解决 此处对应的 DEMO 使用了 **双向绑定** 导致可以关闭【一种关闭了的'假象'】。*/}
{this.slots.header ? this.slots.header({fullscreen, closeDrawer}) :
<DrawerHeader onToggleFullScreen={fullscreen} onClose={closeDrawer} />
Expand Down
Loading