2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-22 10:30:34 +03:00

fix: memory leak when positioning with popper (#1094)

* fix: memory leak when positioning with popper
* docs: update calculate position docs

Co-authored-by: Jeff <sagalbot@gmail.com>
This commit is contained in:
Rafał Gałka
2020-03-10 03:08:57 +01:00
committed by GitHub
parent 531949447c
commit f2479434e4
4 changed files with 29 additions and 9 deletions
@@ -22,7 +22,7 @@ import { createPopper } from '@popperjs/core';
export default { export default {
data: () => ({countries, placement: 'top'}), data: () => ({countries, placement: 'top'}),
methods: { methods: {
withPopper (dropdownList, component, {width},) { withPopper (dropdownList, component, {width}) {
/** /**
* We need to explicitly define the dropdown width since * We need to explicitly define the dropdown width since
* it is usually inherited from the parent with CSS. * it is usually inherited from the parent with CSS.
@@ -39,7 +39,7 @@ export default {
* wrapper so that we can set some styles for when the dropdown is placed * wrapper so that we can set some styles for when the dropdown is placed
* above. * above.
*/ */
createPopper(component.$refs.toggle, dropdownList, { const popper = createPopper(component.$refs.toggle, dropdownList, {
placement: this.placement, placement: this.placement,
modifiers: [ modifiers: [
{ {
@@ -56,6 +56,12 @@ export default {
}, },
}] }]
}); });
/**
* To prevent memory leaks Popper needs to be destroyed.
* If you return function, it will be called just before dropdown is removed from DOM.
*/
return () => popper.destroy();
} }
} }
}; };
+4
View File
@@ -128,6 +128,9 @@ transition: {
When `appendToBody` is true, this function is responsible for positioning the drop down list. When `appendToBody` is true, this function is responsible for positioning the drop down list.
If a function is returned from `calculatePosition`, it will be called when the drop down list
is removed from the DOM. This allows for any garbage collection you may need to do.
See [Dropdown Position](../guide/positioning.md) for more details. See [Dropdown Position](../guide/positioning.md) for more details.
```js ```js
@@ -139,6 +142,7 @@ calculatePosition: {
* @param width {string} calculated width in pixels of the dropdown menu * @param width {string} calculated width in pixels of the dropdown menu
* @param top {string} absolute position top value in pixels relative to the document * @param top {string} absolute position top value in pixels relative to the document
* @param left {string} absolute position left value in pixels relative to the document * @param left {string} absolute position left value in pixels relative to the document
* @return {function|void}
*/ */
default(dropdownList, component, {width, top, left}) { default(dropdownList, component, {width, top, left}) {
dropdownList.style.top = top; dropdownList.style.top = top;
+8 -3
View File
@@ -537,9 +537,13 @@
}, },
/** /**
* When `appendToBody` is true, this function * When `appendToBody` is true, this function is responsible for
* is responsible for positioning the drop * positioning the drop down list.
* down list. *
* If a function is returned from `calculatePosition`, it will
* be called when the drop down list is removed from the DOM.
* This allows for any garbage collection you may need to do.
*
* @since v3.7.0 * @since v3.7.0
* @see http://vue-select.org/guide/positioning.html * @see http://vue-select.org/guide/positioning.html
*/ */
@@ -551,6 +555,7 @@
* @param width {string} calculated width in pixels of the dropdown menu * @param width {string} calculated width in pixels of the dropdown menu
* @param top {string} absolute position top value in pixels relative to the document * @param top {string} absolute position top value in pixels relative to the document
* @param left {string} absolute position left value in pixels relative to the document * @param left {string} absolute position left value in pixels relative to the document
* @return {function|void}
*/ */
default(dropdownList, component, {width, top, left}) { default(dropdownList, component, {width, top, left}) {
dropdownList.style.top = top; dropdownList.style.top = top;
+9 -4
View File
@@ -3,7 +3,7 @@ export default {
if (context.appendToBody) { if (context.appendToBody) {
const {height, top, left} = context.$refs.toggle.getBoundingClientRect(); const {height, top, left} = context.$refs.toggle.getBoundingClientRect();
context.calculatePosition(el, context, { el.unbindPosition = context.calculatePosition(el, context, {
width: context.$refs.toggle.clientWidth + 'px', width: context.$refs.toggle.clientWidth + 'px',
top: (window.scrollY + top + height) + 'px', top: (window.scrollY + top + height) + 'px',
left: (window.scrollX + left) + 'px', left: (window.scrollX + left) + 'px',
@@ -13,9 +13,14 @@ export default {
} }
}, },
unbind (el, bindings, vnode) { unbind (el, bindings, {context}) {
if (vnode.context.appendToBody && el.parentNode) { if (context.appendToBody) {
el.parentNode.removeChild(el); if (el.unbindPosition && typeof el.unbindPosition === 'function') {
el.unbindPosition();
}
if (el.parentNode) {
el.parentNode.removeChild(el);
}
} }
}, },
} }