diff --git a/docs/demos/views/popup.vue b/docs/demos/views/popup.vue index b73aba431..85741ce59 100644 --- a/docs/demos/views/popup.vue +++ b/docs/demos/views/popup.vue @@ -25,8 +25,12 @@ {{ $t('button5') }} - + {{ $t('button6') }} + {{ $t('button5') }} + + {{ $t('button6') }} + @@ -60,7 +64,8 @@ export default { show1: false, show2: false, show3: false, - show4: false + show4: false, + show5: false }; }, @@ -94,7 +99,6 @@ export default { .van-popup { width: 60%; padding: 20px; - border-radius: 5px; box-sizing: border-box; &--bottom { @@ -109,7 +113,7 @@ export default { overflow-y: scroll; -webkit-overflow-scrolling: touch; } - + .van-tab__pane:not(:first-child) { padding: 10px; line-height: 1.4; diff --git a/packages/image-preview/image-preview.vue b/packages/image-preview/image-preview.vue index 49feed3d7..5a19270a1 100644 --- a/packages/image-preview/image-preview.vue +++ b/packages/image-preview/image-preview.vue @@ -69,7 +69,7 @@ export default create({ // prevent long tap to close component const deltaTime = new Date() - this.touchStartTime; if (deltaTime < 100 && Math.abs(this.deltaX) < 20 && Math.abs(this.deltaY) < 20) { - this.close(); + this.$emit('input', false); } } } diff --git a/packages/mixins/popup/context.js b/packages/mixins/popup/context.js index 824941339..1d02bc857 100644 --- a/packages/mixins/popup/context.js +++ b/packages/mixins/popup/context.js @@ -2,6 +2,7 @@ export default { id: 1, zIndex: 2000, stack: [], + lockCount: 0, plusKey(key) { return this[key]++; diff --git a/packages/mixins/popup/index.js b/packages/mixins/popup/index.js index bca493b4f..89176d3ec 100644 --- a/packages/mixins/popup/index.js +++ b/packages/mixins/popup/index.js @@ -57,14 +57,26 @@ export default { } }, + activated() { + /* istanbul ignore next */ + if (this.value) { + this.open(); + } + }, + beforeDestroy() { this.close(); }, + deactivated() { + /* istanbul ignore next */ + this.close(); + }, + methods: { open() { /* istanbul ignore next */ - if (this.$isServer) { + if (this.$isServer || this.opened) { return; } @@ -73,30 +85,41 @@ export default { context.zIndex = this.zIndex; } - if (this.lockScroll) { - document.body.classList.add('van-overflow-hidden'); - on(document, 'touchstart', this.onTouchStart); - on(document, 'touchmove', this.onTouchMove); - } - + this.opened = true; this.renderOverlay(); - this.$emit('input', true); + + if (this.lockScroll) { + if (!context.lockCount) { + document.body.classList.add('van-overflow-hidden'); + on(document, 'touchstart', this.onTouchStart); + on(document, 'touchmove', this.onTouchMove); + } + context.lockCount++; + } }, close() { - if (this.lockScroll) { - document.body.classList.remove('van-overflow-hidden'); - off(document, 'touchstart', this.onTouchStart); - off(document, 'touchmove', this.onTouchMove); + if (!this.opened) { + return; } + if (this.lockScroll) { + context.lockCount--; + if (!context.lockCount) { + document.body.classList.remove('van-overflow-hidden'); + off(document, 'touchstart', this.onTouchStart); + off(document, 'touchmove', this.onTouchMove); + } + } + + this.opened = false; manager.close(this._popupId); - this.$emit('input', false); }, move() { if (this.getContainer) { this.getContainer().appendChild(this.$el); + /* istanbul ignore if */ } else if (this.$parent) { this.$parent.$el.appendChild(this.$el); } diff --git a/packages/mixins/popup/manager.js b/packages/mixins/popup/manager.js index 73daf599c..68649bb8a 100644 --- a/packages/mixins/popup/manager.js +++ b/packages/mixins/popup/manager.js @@ -9,10 +9,8 @@ const defaultConfig = { export default { open(vm, config) { - const exist = context.stack.some(item => item.vm._popupId === vm._popupId); - /* istanbul ignore next */ - if (!exist) { + if (!context.stack.some(item => item.vm._popupId === vm._popupId)) { const el = vm.$el; const targetNode = el && el.parentNode && el.parentNode.nodeType !== 11 ? el.parentNode : document.body; context.stack.push({ vm, config, targetNode }); @@ -66,7 +64,7 @@ export default { if (context.top) { const { vm } = context.top; vm.$emit('click-overlay'); - vm.closeOnClickOverlay && vm.close(); + vm.closeOnClickOverlay && vm.$emit('input', false); } } }; diff --git a/test/specs/popup.spec.js b/test/specs/popup.spec.js index 6676c532e..e40bd51b5 100644 --- a/test/specs/popup.spec.js +++ b/test/specs/popup.spec.js @@ -24,7 +24,8 @@ describe('Popup', () => { propsData: { value: false, zIndex: 100, - overlay: false + overlay: false, + lockScroll: false } }); @@ -60,30 +61,6 @@ describe('Popup', () => { expect(wrapper.instance().currentTransition).to.equal('popup-fade'); }); - it('popup prevent scroll', (done) => { - wrapper = mount(Popup, { - propsData: { - value: true - } - }); - - expect(wrapper.hasClass('van-popup')).to.be.true; - - setTimeout(() => { - expect(wrapper.element.style.display).to.equal(''); - wrapper.vm.value = false; - triggerTouch(document, 'touchstart', 0, 0); - triggerTouch(document, 'touchmove', 0, 10); - triggerTouch(document, 'touchmove', 0, 30); - triggerTouch(document, 'touchmove', 0, -30); - - setTimeout(() => { - expect(wrapper.element.style.display).to.equal('none'); - done(); - }, 500); - }, 300); - }); - it('popup modal', (done) => { wrapper = mount(Popup, { propsData: { @@ -113,6 +90,30 @@ describe('Popup', () => { }, 300); }); + it('popup prevent scroll', (done) => { + wrapper = mount(Popup, { + propsData: { + value: true + } + }); + + expect(wrapper.hasClass('van-popup')).to.be.true; + + setTimeout(() => { + expect(wrapper.element.style.display).to.equal(''); + wrapper.vm.value = false; + triggerTouch(document, 'touchstart', 0, 0); + triggerTouch(document, 'touchmove', 0, 10); + triggerTouch(document, 'touchmove', 0, 30); + triggerTouch(document, 'touchmove', 0, -30); + + setTimeout(() => { + expect(wrapper.element.style.display).to.equal('none'); + done(); + }, 500); + }, 300); + }); + it('treat empty string as true for boolean props', () => { wrapper = mount(Popup, { propsData: { @@ -127,7 +128,9 @@ describe('Popup', () => { it('get container prop', done => { const testNode = document.createElement('div'); + const testNode2 = document.createElement('div'); document.body.appendChild(testNode); + document.body.appendChild(testNode2); wrapper = mount(Popup, { propsData: { @@ -136,11 +139,44 @@ describe('Popup', () => { }); expect(wrapper.vm.$el.parentNode === testNode).to.be.true; - wrapper.vm.getContainer = () => document.body; + wrapper.vm.getContainer = () => testNode2; setTimeout(() => { - expect(wrapper.vm.$el.parentNode === document.body).to.be.true; + expect(wrapper.vm.$el.parentNode === testNode2).to.be.true; + wrapper.vm.getContainer = null; done(); }, 100); }); + + it('watch overlay change', done => { + const testNode = document.createElement('div'); + document.body.appendChild(testNode); + + wrapper = mount(Popup, { + propsData: { + overlay: false, + getContainer: () => testNode + } + }); + + expect(testNode.querySelectorAll('.van-modal').length).to.equal(0); + wrapper.vm.overlay = true; + setTimeout(() => { + expect(testNode.querySelectorAll('.van-modal').length).to.equal(1); + done(); + }, 100); + }); + + it('popup lock scroll', done => { + wrapper = mount(Popup, { + propsData: { + value: true + } + }); + + setTimeout(() => { + expect(document.body.classList.contains('van-overflow-hidden')).to.be.true; + done(); + }, 50); + }); });