[bugfix] Popup should remove event handler when destroyed (#477)

This commit is contained in:
neverland 2017-12-25 14:28:10 +08:00 committed by GitHub
parent 719d1f9b0a
commit 2d2a368e2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 58 deletions

View File

@ -31,8 +31,8 @@
<demo-block :title="$t('uneditable')"> <demo-block :title="$t('uneditable')">
<van-contact-card <van-contact-card
type="edit" type="edit"
:name="list[0].name" :name="mockContact.name"
:tel="list[0].tel" :tel="mockContact.tel"
:editable="false" :editable="false"
/> />
</demo-block> </demo-block>
@ -62,14 +62,18 @@ export default {
}, },
created() { created() {
this.list.push({ this.list.push(this.mockContact);
name: this.$t('name'),
tel: '13000000000',
id: 0
});
}, },
computed: { computed: {
mockContact() {
return {
name: this.$t('name'),
tel: '13000000000',
id: 0
};
},
cardType() { cardType() {
return this.chosenContactId !== null ? 'edit' : 'add'; return this.chosenContactId !== null ? 'edit' : 'add';
}, },
@ -102,7 +106,7 @@ export default {
this.showList = false; this.showList = false;
if (this.isEdit) { if (this.isEdit) {
this.list = this.list.map(item => item.id === info.id ? info : item); this.list = this.list.map(item => (item.id === info.id ? info : item));
} else { } else {
this.list.push(info); this.list.push(info);
} }

View File

@ -96,12 +96,12 @@
"uppercamelcase": "^3.0.0", "uppercamelcase": "^3.0.0",
"url-loader": "^0.6.2", "url-loader": "^0.6.2",
"vant-doc": "0.3.19", "vant-doc": "0.3.19",
"vue": "^2.5.11", "vue": "^2.5.13",
"vue-loader": "^13.6.0", "vue-loader": "^13.6.1",
"vue-router": "^3.0.1", "vue-router": "^3.0.1",
"vue-sfc-compiler": "^0.0.6", "vue-sfc-compiler": "^0.0.6",
"vue-style-loader": "^3.0.0", "vue-style-loader": "^3.0.0",
"vue-template-compiler": "^2.5.11", "vue-template-compiler": "^2.5.13",
"vue-template-es2015-compiler": "^1.6.0", "vue-template-es2015-compiler": "^1.6.0",
"webpack": "^3.10.0", "webpack": "^3.10.0",
"webpack-bundle-analyzer": "^2.9.1", "webpack-bundle-analyzer": "^2.9.1",

View File

@ -1,10 +1,9 @@
const PopupContext = { const PopupContext = {
idSeed: 1, idSeed: 1,
zIndex: 2000, zIndex: 2000,
instances: {},
stack: [], stack: [],
plusKeyByOne(key) { plusKey(key) {
return this[key]++; return this[key]++;
}, },

View File

@ -1,5 +1,5 @@
import manager from './popup-manager'; import manager from './manager';
import context from './popup-context'; import context from './context';
import scrollUtils from '../../utils/scroll'; import scrollUtils from '../../utils/scroll';
export default { export default {
@ -32,8 +32,7 @@ export default {
}, },
beforeMount() { beforeMount() {
this._popupId = 'popup-' + context.plusKeyByOne('idSeed'); this._popupId = 'popup-' + context.plusKey('idSeed');
context.instances[this._popupId] = this;
}, },
data() { data() {
@ -55,14 +54,12 @@ export default {
}, },
watchTouchMove(e) { watchTouchMove(e) {
const pos = this.pos; const { pos } = this;
const dx = e.touches[0].clientX - pos.x; const dx = e.touches[0].clientX - pos.x;
const dy = e.touches[0].clientY - pos.y; const dy = e.touches[0].clientY - pos.y;
const direction = dy > 0 ? '10' : '01'; const direction = dy > 0 ? '10' : '01';
const el = scrollUtils.getScrollEventTarget(e.target, this.$el); const el = scrollUtils.getScrollEventTarget(e.target, this.$el);
const scrollTop = el.scrollTop; const { scrollHeight, offsetHeight, scrollTop } = el;
const scrollHeight = el.scrollHeight;
const offsetHeight = el.offsetHeight;
const isVertical = Math.abs(dx) < Math.abs(dy); const isVertical = Math.abs(dx) < Math.abs(dy);
let status = '11'; let status = '11';
@ -92,10 +89,10 @@ export default {
} }
if (this.overlay) { if (this.overlay) {
manager.openModal({ manager.openModal(this, {
id: this._popupId, id: this._popupId,
zIndex: context.plusKeyByOne('zIndex'),
dom: this.$el, dom: this.$el,
zIndex: context.plusKey('zIndex'),
className: this.overlayClass, className: this.overlayClass,
customStyle: this.overlayStyle customStyle: this.overlayStyle
}); });
@ -105,12 +102,12 @@ export default {
} }
} }
this.$el.style.zIndex = context.plusKeyByOne('zIndex'); this.$el.style.zIndex = context.plusKey('zIndex');
this.opened = true; this.opened = true;
if (this.preventScroll) { if (this.preventScroll) {
document.addEventListener('touchstart', this.recordPosition, false); document.addEventListener('touchstart', this.recordPosition);
document.addEventListener('touchmove', this.watchTouchMove, false); document.addEventListener('touchmove', this.watchTouchMove);
} }
}, },
@ -120,11 +117,6 @@ export default {
} }
this.$emit('input', false); this.$emit('input', false);
if (this.lockOnScroll) {
document.body.classList.remove('van-overflow-hidden');
}
this.opened = false; this.opened = false;
this.doAfterClose(); this.doAfterClose();
}, },
@ -132,18 +124,18 @@ export default {
doAfterClose() { doAfterClose() {
manager.closeModal(this._popupId); manager.closeModal(this._popupId);
if (this.lockOnScroll) {
document.body.classList.remove('van-overflow-hidden');
}
if (this.preventScroll) { if (this.preventScroll) {
document.removeEventListener('touchstart', this.recordPosition, false); document.removeEventListener('touchstart', this.recordPosition);
document.removeEventListener('touchmove', this.watchTouchMove, false); document.removeEventListener('touchmove', this.watchTouchMove);
} }
} }
}, },
beforeDestroy() { beforeDestroy() {
context.instances[this._popupId] = null; this.doAfterClose();
manager.closeModal(this._popupId);
if (this.lockOnScroll) {
document.body.classList.remove('van-overflow-hidden');
}
} }
}; };

View File

@ -1,13 +1,13 @@
import Vue from 'vue'; import Vue from 'vue';
import Modal from './Modal'; import Modal from './Modal';
import context from './popup-context'; import context from './context';
const modalDefaultConfig = { const modalDefaultConfig = {
className: '', className: '',
customStyle: {} customStyle: {}
}; };
const PopupManager = { const manager = {
getModal() { getModal() {
let { modal } = context; let { modal } = context;
@ -17,7 +17,7 @@ const PopupManager = {
el: document.createElement('div') el: document.createElement('div')
}); });
modal.$on('click', () => { modal.$on('click', () => {
PopupManager.handleOverlayClick(); manager.onClickOverlay();
}); });
context.modal = modal; context.modal = modal;
@ -27,23 +27,23 @@ const PopupManager = {
}, },
// close popup when click modal && closeOnClickOverlay is true // close popup when click modal && closeOnClickOverlay is true
handleOverlayClick() { onClickOverlay() {
const { top } = context; const { top } = context;
if (top) { if (top) {
const instance = context.instances[top.id]; const { instance } = top;
if (instance && instance.closeOnClickOverlay) { if (instance && instance.closeOnClickOverlay) {
instance.close(); instance.close();
} }
} }
}, },
openModal(config) { openModal(instance, config) {
const { id, dom } = config; const { id, dom } = config;
const exist = context.stack.some(item => item.id === id); const exist = context.stack.some(item => item.id === id);
if (!exist) { if (!exist) {
const targetNode = dom && dom.parentNode && dom.parentNode.nodeType !== 11 ? dom.parentNode : document.body; const targetNode = dom && dom.parentNode && dom.parentNode.nodeType !== 11 ? dom.parentNode : document.body;
context.stack.push({ id, config, targetNode }); context.stack.push({ instance, id, config, targetNode });
this.updateModal(); this.updateModal();
}; };
}, },
@ -63,16 +63,15 @@ const PopupManager = {
updateModal() { updateModal() {
const modal = this.getModal(); const modal = this.getModal();
const el = modal.$el;
if (el.parentNode) { if (modal.$el.parentNode) {
modal.visible = false; modal.visible = false;
} }
if (context.top) { if (context.top) {
const { targetNode, config } = context.top; const { targetNode, config } = context.top;
targetNode.appendChild(el); targetNode.appendChild(modal.$el);
Object.assign(modal, { Object.assign(modal, {
...modalDefaultConfig, ...modalDefaultConfig,
...config, ...config,
@ -82,4 +81,4 @@ const PopupManager = {
} }
}; };
export default PopupManager; export default manager;

View File

@ -6696,9 +6696,9 @@ vue-lazyload@^1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/vue-lazyload/-/vue-lazyload-1.1.4.tgz#94dbb3fcb047f147f37900c0e22ad4fd478e31c4" resolved "https://registry.yarnpkg.com/vue-lazyload/-/vue-lazyload-1.1.4.tgz#94dbb3fcb047f147f37900c0e22ad4fd478e31c4"
vue-loader@^13.6.0: vue-loader@^13.6.1:
version "13.6.0" version "13.6.1"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.6.0.tgz#c1c9570e1e57475f8acb02cda35551b812f88086" resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.6.1.tgz#3ad365271b3db382722ab2eb0d6936d8d52ec2ce"
dependencies: dependencies:
consolidate "^0.14.0" consolidate "^0.14.0"
hash-sum "^1.0.2" hash-sum "^1.0.2"
@ -6729,9 +6729,9 @@ vue-style-loader@^3.0.0:
hash-sum "^1.0.2" hash-sum "^1.0.2"
loader-utils "^1.0.2" loader-utils "^1.0.2"
vue-template-compiler@^2.5.11: vue-template-compiler@^2.5.13:
version "2.5.11" version "2.5.13"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.11.tgz#7dda6905e464ff173c8e70e1dfd1769a7888b7e8" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.13.tgz#12a2aa0ecd6158ac5e5f14d294b0993f399c3d38"
dependencies: dependencies:
de-indent "^1.0.2" de-indent "^1.0.2"
he "^1.1.0" he "^1.1.0"
@ -6740,9 +6740,9 @@ vue-template-es2015-compiler@^1.6.0:
version "1.6.0" version "1.6.0"
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
vue@^2.5.11: vue@^2.5.13:
version "2.5.11" version "2.5.13"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.11.tgz#80ca2657aa81f03545cd8dd5a2f55454641e6405" resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.13.tgz#95bd31e20efcf7a7f39239c9aa6787ce8cf578e1"
watchpack@^1.4.0: watchpack@^1.4.0:
version "1.4.0" version "1.4.0"