Popper: fix memory leak on route change (#9757)

pull/9771/head
syn-zeta 2018-02-10 18:59:32 -08:00 committed by 杨奕
parent e4abaf7b6e
commit 1b3832f009
2 changed files with 14 additions and 19 deletions

View File

@ -240,7 +240,6 @@
if (typeof this.state.updateCallback === 'function') { if (typeof this.state.updateCallback === 'function') {
this.state.updateCallback(data); this.state.updateCallback(data);
} }
}; };
/** /**
@ -438,7 +437,6 @@
popperOffsets.width = popperRect.width; popperOffsets.width = popperRect.width;
popperOffsets.height = popperRect.height; popperOffsets.height = popperRect.height;
return { return {
popper: popperOffsets, popper: popperOffsets,
reference: referenceOffsets reference: referenceOffsets
@ -464,6 +462,7 @@
target = root; target = root;
} }
target.addEventListener('scroll', this.state.updateBound); target.addEventListener('scroll', this.state.updateBound);
this.state.scrollTarget = target;
} }
}; };
@ -476,13 +475,9 @@
Popper.prototype._removeEventListeners = function() { Popper.prototype._removeEventListeners = function() {
// NOTE: 1 DOM access here // NOTE: 1 DOM access here
root.removeEventListener('resize', this.state.updateBound); root.removeEventListener('resize', this.state.updateBound);
if (this._options.boundariesElement !== 'window') { if (this._options.boundariesElement !== 'window' && this.state.scrollTarget) {
var target = getScrollParent(this._reference); this.state.scrollTarget.removeEventListener('scroll', this.state.updateBound);
// here it could be both `body` or `documentElement` thanks to Firefox, we then check both this.state.scrollTarget = null;
if (target === root.document.body || target === root.document.documentElement) {
target = root;
}
target.removeEventListener('scroll', this.state.updateBound);
} }
this.state.updateBound = null; this.state.updateBound = null;
}; };
@ -519,13 +514,13 @@
var scrollParent = getScrollParent(this._popper); var scrollParent = getScrollParent(this._popper);
var offsetParentRect = getOffsetRect(offsetParent); var offsetParentRect = getOffsetRect(offsetParent);
// Thanks the fucking native API, `document.body.scrollTop` & `document.documentElement.scrollTop` // Thanks the fucking native API, `document.body.scrollTop` & `document.documentElement.scrollTop`
var getScrollTopValue = function (element) { var getScrollTopValue = function (element) {
return element == document.body ? Math.max(document.documentElement.scrollTop, document.body.scrollTop) : element.scrollTop; return element == document.body ? Math.max(document.documentElement.scrollTop, document.body.scrollTop) : element.scrollTop;
} }
var getScrollLeftValue = function (element) { var getScrollLeftValue = function (element) {
return element == document.body ? Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) : element.scrollLeft; return element == document.body ? Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) : element.scrollLeft;
} }
// if the popper is fixed we don't have to substract scrolling from the boundaries // if the popper is fixed we don't have to substract scrolling from the boundaries
var scrollTop = data.offsets.popper.position === 'fixed' ? 0 : getScrollTopValue(scrollParent); var scrollTop = data.offsets.popper.position === 'fixed' ? 0 : getScrollTopValue(scrollParent);

View File

@ -129,9 +129,9 @@ export default {
} }
}, },
doDestroy() { doDestroy(forceDestroy) {
/* istanbul ignore if */ /* istanbul ignore if */
if (this.showPopper || !this.popperJS) return; if (!this.popperJS || (this.showPopper && !forceDestroy)) return;
this.popperJS.destroy(); this.popperJS.destroy();
this.popperJS = null; this.popperJS = null;
}, },
@ -184,7 +184,7 @@ export default {
}, },
beforeDestroy() { beforeDestroy() {
this.doDestroy(); this.doDestroy(true);
if (this.popperElm && this.popperElm.parentNode === document.body) { if (this.popperElm && this.popperElm.parentNode === document.body) {
this.popperElm.removeEventListener('click', stop); this.popperElm.removeEventListener('click', stop);
document.body.removeChild(this.popperElm); document.body.removeChild(this.popperElm);