[bugfix] Popup: lock-scroll not work when open multi popup (#842)

This commit is contained in:
neverland 2018-04-10 10:39:54 +08:00 committed by GitHub
parent 91f44010e7
commit 1b6f9ba075
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 49 deletions

View File

@ -25,8 +25,12 @@
</van-popup> </van-popup>
<van-button @click="show4 = true">{{ $t('button5') }}</van-button> <van-button @click="show4 = true">{{ $t('button5') }}</van-button>
<van-popup v-model="show4" position="right" :overlay="false"> <van-popup v-model="show4" position="right">
<van-button @click="show4 = false">{{ $t('button6') }}</van-button> <van-button @click="show4 = false">{{ $t('button6') }}</van-button>
<van-button @click="show5 = true">{{ $t('button5') }}</van-button>
<van-popup v-model="show5" position="right">
<van-button @click="show5 = false">{{ $t('button6') }}</van-button>
</van-popup>
</van-popup> </van-popup>
</demo-block> </demo-block>
</demo-section> </demo-section>
@ -60,7 +64,8 @@ export default {
show1: false, show1: false,
show2: false, show2: false,
show3: false, show3: false,
show4: false show4: false,
show5: false
}; };
}, },
@ -94,7 +99,6 @@ export default {
.van-popup { .van-popup {
width: 60%; width: 60%;
padding: 20px; padding: 20px;
border-radius: 5px;
box-sizing: border-box; box-sizing: border-box;
&--bottom { &--bottom {

View File

@ -69,7 +69,7 @@ export default create({
// prevent long tap to close component // prevent long tap to close component
const deltaTime = new Date() - this.touchStartTime; const deltaTime = new Date() - this.touchStartTime;
if (deltaTime < 100 && Math.abs(this.deltaX) < 20 && Math.abs(this.deltaY) < 20) { if (deltaTime < 100 && Math.abs(this.deltaX) < 20 && Math.abs(this.deltaY) < 20) {
this.close(); this.$emit('input', false);
} }
} }
} }

View File

@ -2,6 +2,7 @@ export default {
id: 1, id: 1,
zIndex: 2000, zIndex: 2000,
stack: [], stack: [],
lockCount: 0,
plusKey(key) { plusKey(key) {
return this[key]++; return this[key]++;

View File

@ -57,14 +57,26 @@ export default {
} }
}, },
activated() {
/* istanbul ignore next */
if (this.value) {
this.open();
}
},
beforeDestroy() { beforeDestroy() {
this.close(); this.close();
}, },
deactivated() {
/* istanbul ignore next */
this.close();
},
methods: { methods: {
open() { open() {
/* istanbul ignore next */ /* istanbul ignore next */
if (this.$isServer) { if (this.$isServer || this.opened) {
return; return;
} }
@ -73,30 +85,41 @@ export default {
context.zIndex = this.zIndex; context.zIndex = this.zIndex;
} }
this.opened = true;
this.renderOverlay();
if (this.lockScroll) { if (this.lockScroll) {
if (!context.lockCount) {
document.body.classList.add('van-overflow-hidden'); document.body.classList.add('van-overflow-hidden');
on(document, 'touchstart', this.onTouchStart); on(document, 'touchstart', this.onTouchStart);
on(document, 'touchmove', this.onTouchMove); on(document, 'touchmove', this.onTouchMove);
} }
context.lockCount++;
this.renderOverlay(); }
this.$emit('input', true);
}, },
close() { close() {
if (!this.opened) {
return;
}
if (this.lockScroll) { if (this.lockScroll) {
context.lockCount--;
if (!context.lockCount) {
document.body.classList.remove('van-overflow-hidden'); document.body.classList.remove('van-overflow-hidden');
off(document, 'touchstart', this.onTouchStart); off(document, 'touchstart', this.onTouchStart);
off(document, 'touchmove', this.onTouchMove); off(document, 'touchmove', this.onTouchMove);
} }
}
this.opened = false;
manager.close(this._popupId); manager.close(this._popupId);
this.$emit('input', false);
}, },
move() { move() {
if (this.getContainer) { if (this.getContainer) {
this.getContainer().appendChild(this.$el); this.getContainer().appendChild(this.$el);
/* istanbul ignore if */
} else if (this.$parent) { } else if (this.$parent) {
this.$parent.$el.appendChild(this.$el); this.$parent.$el.appendChild(this.$el);
} }

View File

@ -9,10 +9,8 @@ const defaultConfig = {
export default { export default {
open(vm, config) { open(vm, config) {
const exist = context.stack.some(item => item.vm._popupId === vm._popupId);
/* istanbul ignore next */ /* istanbul ignore next */
if (!exist) { if (!context.stack.some(item => item.vm._popupId === vm._popupId)) {
const el = vm.$el; const el = vm.$el;
const targetNode = el && el.parentNode && el.parentNode.nodeType !== 11 ? el.parentNode : document.body; const targetNode = el && el.parentNode && el.parentNode.nodeType !== 11 ? el.parentNode : document.body;
context.stack.push({ vm, config, targetNode }); context.stack.push({ vm, config, targetNode });
@ -66,7 +64,7 @@ export default {
if (context.top) { if (context.top) {
const { vm } = context.top; const { vm } = context.top;
vm.$emit('click-overlay'); vm.$emit('click-overlay');
vm.closeOnClickOverlay && vm.close(); vm.closeOnClickOverlay && vm.$emit('input', false);
} }
} }
}; };

View File

@ -24,7 +24,8 @@ describe('Popup', () => {
propsData: { propsData: {
value: false, value: false,
zIndex: 100, zIndex: 100,
overlay: false overlay: false,
lockScroll: false
} }
}); });
@ -60,30 +61,6 @@ describe('Popup', () => {
expect(wrapper.instance().currentTransition).to.equal('popup-fade'); 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) => { it('popup modal', (done) => {
wrapper = mount(Popup, { wrapper = mount(Popup, {
propsData: { propsData: {
@ -113,6 +90,30 @@ describe('Popup', () => {
}, 300); }, 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', () => { it('treat empty string as true for boolean props', () => {
wrapper = mount(Popup, { wrapper = mount(Popup, {
propsData: { propsData: {
@ -127,7 +128,9 @@ describe('Popup', () => {
it('get container prop', done => { it('get container prop', done => {
const testNode = document.createElement('div'); const testNode = document.createElement('div');
const testNode2 = document.createElement('div');
document.body.appendChild(testNode); document.body.appendChild(testNode);
document.body.appendChild(testNode2);
wrapper = mount(Popup, { wrapper = mount(Popup, {
propsData: { propsData: {
@ -136,11 +139,44 @@ describe('Popup', () => {
}); });
expect(wrapper.vm.$el.parentNode === testNode).to.be.true; expect(wrapper.vm.$el.parentNode === testNode).to.be.true;
wrapper.vm.getContainer = () => document.body; wrapper.vm.getContainer = () => testNode2;
setTimeout(() => { 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(); done();
}, 100); }, 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);
});
}); });