From c5c2e9690dc72838237ca82966c726594e721b7a Mon Sep 17 00:00:00 2001 From: neverland Date: Sun, 24 May 2020 16:24:20 +0800 Subject: [PATCH] refactor(Popup): create overlay for every popup (#6357) --- .../test/__snapshots__/index.spec.js.snap | 27 ------- src/dropdown-menu/test/index.spec.js | 6 +- src/mixins/popup/context.ts | 6 +- src/mixins/popup/index.js | 28 +++++-- src/mixins/popup/overlay.ts | 79 ++++++++----------- 5 files changed, 62 insertions(+), 84 deletions(-) diff --git a/src/dropdown-menu/test/__snapshots__/index.spec.js.snap b/src/dropdown-menu/test/__snapshots__/index.spec.js.snap index e194ab060..a32d0ba96 100644 --- a/src/dropdown-menu/test/__snapshots__/index.spec.js.snap +++ b/src/dropdown-menu/test/__snapshots__/index.spec.js.snap @@ -343,30 +343,3 @@ exports[`title slot 1`] = ` `; - -exports[`toggle method 1`] = ` -
-
-
-
-
-
-
-
-
-
-
-`; - -exports[`toggle method 2`] = ` -
-
-
-
-
-
- -
-
-
-`; diff --git a/src/dropdown-menu/test/index.spec.js b/src/dropdown-menu/test/index.spec.js index b956e5a3e..b92047b4b 100644 --- a/src/dropdown-menu/test/index.spec.js +++ b/src/dropdown-menu/test/index.spec.js @@ -224,12 +224,14 @@ test('toggle method', async (done) => { // show this.$refs.item.toggle(true, { immediate: true }); await later(); - expect(wrapper).toMatchSnapshot(); + + const content = wrapper.find('.van-dropdown-item__content'); + expect(content.element.style.display).toEqual(''); // hide this.$refs.item.toggle(false, { immediate: true }); await later(); - expect(wrapper).toMatchSnapshot(); + expect(content.element.style.display).toEqual('none'); done(); }, diff --git a/src/mixins/popup/context.ts b/src/mixins/popup/context.ts index 879954da4..6ab98f914 100644 --- a/src/mixins/popup/context.ts +++ b/src/mixins/popup/context.ts @@ -2,6 +2,7 @@ import { OverlayConfig } from './overlay'; export type StackItem = { vm: any; + overlay: any; config: OverlayConfig; }; @@ -9,8 +10,7 @@ export const context = { zIndex: 2000, lockCount: 0, stack: [] as StackItem[], - - get top(): StackItem { - return this.stack[this.stack.length - 1]; + find(vm: any): StackItem | undefined { + return this.stack.filter((item) => item.vm === vm)[0]; }, }; diff --git a/src/mixins/popup/index.js b/src/mixins/popup/index.js index cb9529cf0..2180ed6f8 100644 --- a/src/mixins/popup/index.js +++ b/src/mixins/popup/index.js @@ -1,6 +1,11 @@ // Context import { context } from './context'; -import { openOverlay, closeOverlay, updateOverlay } from './overlay'; +import { + openOverlay, + closeOverlay, + updateOverlay, + removeOverlay, +} from './overlay'; // Utils import { on, off, preventDefault } from '../../utils/dom/event'; @@ -94,7 +99,8 @@ export function PopupMixin(options = {}) { }, beforeDestroy() { - this.close(); + this.removeLock(); + removeOverlay(this); if (this.getContainer) { removeNode(this.$el); @@ -123,7 +129,10 @@ export function PopupMixin(options = {}) { this.opened = true; this.renderOverlay(); + this.addLock(); + }, + addLock() { if (this.lockScroll) { on(document, 'touchstart', this.touchStart); on(document, 'touchmove', this.onTouchMove); @@ -135,11 +144,7 @@ export function PopupMixin(options = {}) { } }, - close() { - if (!this.opened) { - return; - } - + removeLock() { if (this.lockScroll) { context.lockCount--; off(document, 'touchstart', this.touchStart); @@ -149,9 +154,16 @@ export function PopupMixin(options = {}) { document.body.classList.remove('van-overflow-hidden'); } } + }, + + close() { + if (!this.opened) { + return; + } - this.opened = false; closeOverlay(this); + this.opened = false; + this.removeLock(); this.$emit('input', false); }, diff --git a/src/mixins/popup/overlay.ts b/src/mixins/popup/overlay.ts index 84a9fb4af..9bf10c644 100644 --- a/src/mixins/popup/overlay.ts +++ b/src/mixins/popup/overlay.ts @@ -1,6 +1,7 @@ import Overlay from '../../overlay'; import { context } from './context'; import { mount } from '../../utils/functional'; +import { removeNode } from '../../utils/dom/node'; export type OverlayConfig = { zIndex?: number; @@ -13,71 +14,61 @@ const defaultConfig: OverlayConfig = { customStyle: {}, }; -let overlay: any; - -// close popup when click overlay && closeOnClickOverlay is true -function onClickOverlay(): void { - if (context.top) { - const { vm } = context.top; - vm.$emit('click-overlay'); - - if (vm.closeOnClickOverlay) { - if (vm.onClickOverlay) { - vm.onClickOverlay(); - } else { - vm.close(); - } - } - } -} - -function mountOverlay() { - overlay = mount(Overlay, { +function mountOverlay(vm: any) { + return mount(Overlay, { on: { - click: onClickOverlay, + // close popup when overlay clicked & closeOnClickOverlay is true + click() { + vm.$emit('click-overlay'); + + if (vm.closeOnClickOverlay) { + if (vm.onClickOverlay) { + vm.onClickOverlay(); + } else { + vm.close(); + } + } + }, }, }); } -export function updateOverlay(): void { - if (!overlay) { - mountOverlay(); - } - - if (context.top) { - const { vm, config } = context.top; +export function updateOverlay(vm: any): void { + const item = context.find(vm); + if (item) { const el = vm.$el; + const { config, overlay } = item; + if (el && el.parentNode) { el.parentNode.insertBefore(overlay.$el, el); - } else { - document.body.appendChild(overlay.$el); } Object.assign(overlay, defaultConfig, config, { show: true, }); - } else { - overlay.show = false; } } export function openOverlay(vm: any, config: OverlayConfig): void { - if (!context.stack.some((item) => item.vm === vm)) { - context.stack.push({ vm, config }); - updateOverlay(); + if (!context.find(vm)) { + const overlay = mountOverlay(vm); + context.stack.push({ vm, config, overlay }); } + + updateOverlay(vm); } export function closeOverlay(vm: any): void { - const { stack } = context; - - if (stack.length) { - if (context.top.vm === vm) { - stack.pop(); - updateOverlay(); - } else { - context.stack = stack.filter((item) => item.vm !== vm); - } + const item = context.find(vm); + if (item) { + item.overlay.show = false; + } +} + +export function removeOverlay(vm: any) { + const item = context.find(vm); + if (item) { + removeNode(item.overlay.$el); } }