From 2d2a368e2c649e0fbeb94cd37b06ea7c221a75ab Mon Sep 17 00:00:00 2001 From: neverland Date: Mon, 25 Dec 2017 14:28:10 +0800 Subject: [PATCH] [bugfix] Popup should remove event handler when destroyed (#477) --- docs/demos/views/contact.vue | 20 +++++---- package.json | 6 +-- .../popup/{popup-context.js => context.js} | 3 +- packages/mixins/popup/index.js | 42 ++++++++----------- .../popup/{popup-manager.js => manager.js} | 21 +++++----- yarn.lock | 18 ++++---- 6 files changed, 52 insertions(+), 58 deletions(-) rename packages/mixins/popup/{popup-context.js => context.js} (83%) rename packages/mixins/popup/{popup-manager.js => manager.js} (79%) diff --git a/docs/demos/views/contact.vue b/docs/demos/views/contact.vue index f4fc6e6b8..52d9564c9 100644 --- a/docs/demos/views/contact.vue +++ b/docs/demos/views/contact.vue @@ -31,8 +31,8 @@ @@ -62,14 +62,18 @@ export default { }, created() { - this.list.push({ - name: this.$t('name'), - tel: '13000000000', - id: 0 - }); + this.list.push(this.mockContact); }, computed: { + mockContact() { + return { + name: this.$t('name'), + tel: '13000000000', + id: 0 + }; + }, + cardType() { return this.chosenContactId !== null ? 'edit' : 'add'; }, @@ -102,7 +106,7 @@ export default { this.showList = false; 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 { this.list.push(info); } diff --git a/package.json b/package.json index 8ae6427d5..6cabaf6e2 100644 --- a/package.json +++ b/package.json @@ -96,12 +96,12 @@ "uppercamelcase": "^3.0.0", "url-loader": "^0.6.2", "vant-doc": "0.3.19", - "vue": "^2.5.11", - "vue-loader": "^13.6.0", + "vue": "^2.5.13", + "vue-loader": "^13.6.1", "vue-router": "^3.0.1", "vue-sfc-compiler": "^0.0.6", "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", "webpack": "^3.10.0", "webpack-bundle-analyzer": "^2.9.1", diff --git a/packages/mixins/popup/popup-context.js b/packages/mixins/popup/context.js similarity index 83% rename from packages/mixins/popup/popup-context.js rename to packages/mixins/popup/context.js index 14039e53c..9f3e5da27 100644 --- a/packages/mixins/popup/popup-context.js +++ b/packages/mixins/popup/context.js @@ -1,10 +1,9 @@ const PopupContext = { idSeed: 1, zIndex: 2000, - instances: {}, stack: [], - plusKeyByOne(key) { + plusKey(key) { return this[key]++; }, diff --git a/packages/mixins/popup/index.js b/packages/mixins/popup/index.js index 01241e767..205d9c9ee 100644 --- a/packages/mixins/popup/index.js +++ b/packages/mixins/popup/index.js @@ -1,5 +1,5 @@ -import manager from './popup-manager'; -import context from './popup-context'; +import manager from './manager'; +import context from './context'; import scrollUtils from '../../utils/scroll'; export default { @@ -32,8 +32,7 @@ export default { }, beforeMount() { - this._popupId = 'popup-' + context.plusKeyByOne('idSeed'); - context.instances[this._popupId] = this; + this._popupId = 'popup-' + context.plusKey('idSeed'); }, data() { @@ -55,14 +54,12 @@ export default { }, watchTouchMove(e) { - const pos = this.pos; + const { pos } = this; const dx = e.touches[0].clientX - pos.x; const dy = e.touches[0].clientY - pos.y; const direction = dy > 0 ? '10' : '01'; const el = scrollUtils.getScrollEventTarget(e.target, this.$el); - const scrollTop = el.scrollTop; - const scrollHeight = el.scrollHeight; - const offsetHeight = el.offsetHeight; + const { scrollHeight, offsetHeight, scrollTop } = el; const isVertical = Math.abs(dx) < Math.abs(dy); let status = '11'; @@ -92,10 +89,10 @@ export default { } if (this.overlay) { - manager.openModal({ + manager.openModal(this, { id: this._popupId, - zIndex: context.plusKeyByOne('zIndex'), dom: this.$el, + zIndex: context.plusKey('zIndex'), className: this.overlayClass, 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; if (this.preventScroll) { - document.addEventListener('touchstart', this.recordPosition, false); - document.addEventListener('touchmove', this.watchTouchMove, false); + document.addEventListener('touchstart', this.recordPosition); + document.addEventListener('touchmove', this.watchTouchMove); } }, @@ -120,11 +117,6 @@ export default { } this.$emit('input', false); - - if (this.lockOnScroll) { - document.body.classList.remove('van-overflow-hidden'); - } - this.opened = false; this.doAfterClose(); }, @@ -132,18 +124,18 @@ export default { doAfterClose() { manager.closeModal(this._popupId); + if (this.lockOnScroll) { + document.body.classList.remove('van-overflow-hidden'); + } + if (this.preventScroll) { - document.removeEventListener('touchstart', this.recordPosition, false); - document.removeEventListener('touchmove', this.watchTouchMove, false); + document.removeEventListener('touchstart', this.recordPosition); + document.removeEventListener('touchmove', this.watchTouchMove); } } }, beforeDestroy() { - context.instances[this._popupId] = null; - manager.closeModal(this._popupId); - if (this.lockOnScroll) { - document.body.classList.remove('van-overflow-hidden'); - } + this.doAfterClose(); } }; diff --git a/packages/mixins/popup/popup-manager.js b/packages/mixins/popup/manager.js similarity index 79% rename from packages/mixins/popup/popup-manager.js rename to packages/mixins/popup/manager.js index 1113c5224..319c8da89 100644 --- a/packages/mixins/popup/popup-manager.js +++ b/packages/mixins/popup/manager.js @@ -1,13 +1,13 @@ import Vue from 'vue'; import Modal from './Modal'; -import context from './popup-context'; +import context from './context'; const modalDefaultConfig = { className: '', customStyle: {} }; -const PopupManager = { +const manager = { getModal() { let { modal } = context; @@ -17,7 +17,7 @@ const PopupManager = { el: document.createElement('div') }); modal.$on('click', () => { - PopupManager.handleOverlayClick(); + manager.onClickOverlay(); }); context.modal = modal; @@ -27,23 +27,23 @@ const PopupManager = { }, // close popup when click modal && closeOnClickOverlay is true - handleOverlayClick() { + onClickOverlay() { const { top } = context; if (top) { - const instance = context.instances[top.id]; + const { instance } = top; if (instance && instance.closeOnClickOverlay) { instance.close(); } } }, - openModal(config) { + openModal(instance, config) { const { id, dom } = config; const exist = context.stack.some(item => item.id === id); if (!exist) { 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(); }; }, @@ -63,16 +63,15 @@ const PopupManager = { updateModal() { const modal = this.getModal(); - const el = modal.$el; - if (el.parentNode) { + if (modal.$el.parentNode) { modal.visible = false; } if (context.top) { const { targetNode, config } = context.top; - targetNode.appendChild(el); + targetNode.appendChild(modal.$el); Object.assign(modal, { ...modalDefaultConfig, ...config, @@ -82,4 +81,4 @@ const PopupManager = { } }; -export default PopupManager; +export default manager; diff --git a/yarn.lock b/yarn.lock index 9d57d655c..975c80474 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6696,9 +6696,9 @@ vue-lazyload@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/vue-lazyload/-/vue-lazyload-1.1.4.tgz#94dbb3fcb047f147f37900c0e22ad4fd478e31c4" -vue-loader@^13.6.0: - version "13.6.0" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.6.0.tgz#c1c9570e1e57475f8acb02cda35551b812f88086" +vue-loader@^13.6.1: + version "13.6.1" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.6.1.tgz#3ad365271b3db382722ab2eb0d6936d8d52ec2ce" dependencies: consolidate "^0.14.0" hash-sum "^1.0.2" @@ -6729,9 +6729,9 @@ vue-style-loader@^3.0.0: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.5.11: - version "2.5.11" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.11.tgz#7dda6905e464ff173c8e70e1dfd1769a7888b7e8" +vue-template-compiler@^2.5.13: + version "2.5.13" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.13.tgz#12a2aa0ecd6158ac5e5f14d294b0993f399c3d38" dependencies: de-indent "^1.0.2" he "^1.1.0" @@ -6740,9 +6740,9 @@ vue-template-es2015-compiler@^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" -vue@^2.5.11: - version "2.5.11" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.11.tgz#80ca2657aa81f03545cd8dd5a2f55454641e6405" +vue@^2.5.13: + version "2.5.13" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.13.tgz#95bd31e20efcf7a7f39239c9aa6787ce8cf578e1" watchpack@^1.4.0: version "1.4.0"