From 8e95db293c97d85d567f41d28293545a5453e3fa Mon Sep 17 00:00:00 2001 From: jeremywu <591449570@qq.com> Date: Thu, 22 Oct 2020 14:00:33 +0800 Subject: [PATCH] fix(popper): remove clickouside listener when manual enabled (#450) --- packages/dialog/__tests__/dialog.spec.ts | 2 +- packages/dialog/src/index.ts | 102 ++++++++++++----------- packages/overlay/src/index.vue | 17 ++-- packages/popper/src/index.vue | 49 ++++++----- packages/popper/src/renderers/index.ts | 2 +- packages/popper/src/renderers/mask.ts | 65 ++++++++++++--- packages/popper/src/use-popper/index.ts | 1 + website/docs/en-US/dialog.md | 43 ++++++---- 8 files changed, 175 insertions(+), 106 deletions(-) diff --git a/packages/dialog/__tests__/dialog.spec.ts b/packages/dialog/__tests__/dialog.spec.ts index 3ee9521e71..3ab27ffc99 100644 --- a/packages/dialog/__tests__/dialog.spec.ts +++ b/packages/dialog/__tests__/dialog.spec.ts @@ -97,7 +97,7 @@ describe('Dialog.vue', () => { test('should not have overlay mask when mask is false', () => { const wrapper = _mount({ props: { - mask: false, + modal: false, }, }) diff --git a/packages/dialog/src/index.ts b/packages/dialog/src/index.ts index 1f8312eda5..9d56664ab5 100644 --- a/packages/dialog/src/index.ts +++ b/packages/dialog/src/index.ts @@ -1,14 +1,21 @@ import { + createVNode, defineComponent, + Fragment, Transition, Teleport, h, withDirectives, vShow, + toDisplayString, + renderSlot, + withCtx, } from 'vue' import { TrapFocus } from '@element-plus/directives' +import { stop } from '@element-plus/utils/dom' import { isValidWidthUnit } from '@element-plus/utils/validators' +import { PatchFlags, renderBlock, renderIf } from '@element-plus/utils/vnode' import ElOverlay from '@element-plus/overlay' import { @@ -22,6 +29,13 @@ import { import type { PropType, SetupContext } from 'vue' +const closeIcon = createVNode('i', { class: 'el-dialog__close el-icon el-icon-close' }, null, PatchFlags.HOISTED) +const headerKls = { class: 'el-dialog__header' } +const bodyKls = { class: 'el-dialog__body' } +const titleKls = { class: 'el-dialog__title' } +const footerKls = { class: 'el-dialog__footer', key: 0 } + + export default defineComponent({ name: 'ElDialog', props: { @@ -114,44 +128,38 @@ export default defineComponent({ return null } const { $slots } = this - const closeBtn = this.showClose - ? h( - 'button', - { - type: 'button', - class: 'el-dialog__headerbtn', - ariaLabel: 'close', - onClick: this.handleClose, - }, - h('i', { class: 'el-dialog__close el-icon el-icon-close' }), - ) - : null - const header = h( - 'div', + const closeBtn = renderIf(this.showClose, 'button', { - class: 'el-dialog__header', + type: 'button', + class: 'el-dialog__headerbtn', + ariaLabel: 'close', + onClick: this.handleClose, }, + [closeIcon], + PatchFlags.PROPS, + ['onClick'], + ) + + const header = createVNode( + 'div', + headerKls, [ - $slots.header - ? $slots.header() - : h('span', { class: 'el-dialog__title' }, this.title), + renderSlot($slots, 'header', {}, () => + [createVNode('span', titleKls, toDisplayString(this.title), PatchFlags.TEXT)], + ), closeBtn, ], ) - const body = h( + const body = createVNode( 'div', - { - class: 'el-dialog__body', - }, - $slots.default?.(), + bodyKls, + [renderSlot($slots, 'default')], ) - const footer = $slots.footer - ? h('div', { class: 'el-dialog__footer' }, $slots.footer()) - : null + const footer = renderIf(!!$slots.footer, 'div', footerKls, [renderSlot($slots, 'footer')]) - const dialog = h( + const dialog = createVNode( 'div', { ariaModal: true, @@ -167,14 +175,16 @@ export default defineComponent({ ref: 'dialogRef', role: 'dialog', style: this.style, - onClick: (e: MouseEvent) => e.stopPropagation(), + onClick: stop, }, [header, body, footer], + PatchFlags.STYLE | PatchFlags.CLASS | PatchFlags.PROPS, + ['ariaLabel', 'onClick'], ) const trappedDialog = withDirectives(dialog, [[TrapFocus]]) const overlay = withDirectives( - h( + createVNode( ElOverlay, { mask: this.modal, @@ -182,33 +192,31 @@ export default defineComponent({ zIndex: this.zIndex, }, { - default: () => trappedDialog, + default: withCtx(() => [trappedDialog]), }, - ), - [[vShow, this.visible]], - ) + PatchFlags.PROPS, + ['mask', 'onClick', 'zIndex'], + ), [[vShow, this.visible]]) - const renderer = h( + + const renderer = createVNode( Transition, { name: 'dialog-fade', - onAfterEnter: this.afterEnter, - onAfterLeave: this.afterLeave, + 'onAfter-enter': this.afterEnter, + 'onAfter-leave': this.afterLeave, }, { - default: () => overlay, + default: () => [overlay], }, + PatchFlags.PROPS, + ['onAfter-enter', 'onAfter-leave'], ) - if (this.appendToBody) { - return h( - Teleport, - { - to: 'body', - }, - renderer, - ) - } - return renderer + return renderBlock(Fragment, null, [ + this.appendToBody + ? h(Teleport, { key: 0, to: 'body' }, [renderer]) + : h(Fragment, { key: 1 }, [renderer]), + ]) }, }) diff --git a/packages/overlay/src/index.vue b/packages/overlay/src/index.vue index 4847949259..c98e040e96 100644 --- a/packages/overlay/src/index.vue +++ b/packages/overlay/src/index.vue @@ -1,5 +1,7 @@ -