From d670886250da7f2b38e592568b70e55a1e26138b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacob=20M=C3=BCller?= Date: Wed, 9 Sep 2020 13:35:31 +0200 Subject: [PATCH] fix: component destroy handling on parent destroy --- src/components/modal/helpers/bv-modal.js | 8 +++++--- src/components/toast/helpers/bv-toast.js | 13 ++++++------ src/components/tooltip/helpers/bv-popper.js | 21 +++++++++++++------- src/components/tooltip/helpers/bv-tooltip.js | 10 +++++++++- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/components/modal/helpers/bv-modal.js b/src/components/modal/helpers/bv-modal.js index 2c0770ee54c..1ccca3e71ca 100644 --- a/src/components/modal/helpers/bv-modal.js +++ b/src/components/modal/helpers/bv-modal.js @@ -2,6 +2,7 @@ import { BModal, props as modalProps } from '../modal' import { concat } from '../../../utils/array' import { getComponentConfig } from '../../../utils/config' +import { requestAF } from '../../../utils/dom' import { isUndefined, isFunction } from '../../../utils/inspect' import { assign, @@ -69,10 +70,11 @@ const plugin = Vue => { mounted() { // Self destruct handler const handleDestroy = () => { - const self = this this.$nextTick(() => { - // In a `setTimeout()` to release control back to application - setTimeout(() => self.$destroy(), 0) + // In a `requestAF()` to release control back to application + requestAF(() => { + this.$destroy() + }) }) } // Self destruct if parent destroyed diff --git a/src/components/toast/helpers/bv-toast.js b/src/components/toast/helpers/bv-toast.js index 8c159ab9b6f..ee4798c1006 100644 --- a/src/components/toast/helpers/bv-toast.js +++ b/src/components/toast/helpers/bv-toast.js @@ -63,18 +63,17 @@ const plugin = Vue => { } }, mounted() { - const self = this // Self destruct handler const handleDestroy = () => { // Ensure the toast has been force hidden - self.localShow = false - self.doRender = false - self.$nextTick(() => { - self.$nextTick(() => { + this.localShow = false + this.doRender = false + this.$nextTick(() => { + this.$nextTick(() => { // In a `requestAF()` to release control back to application // and to allow the portal-target time to remove the content requestAF(() => { - self.$destroy() + this.$destroy() }) }) }) @@ -86,7 +85,7 @@ const plugin = Vue => { // Self destruct when toaster is destroyed this.listenOnRoot('bv::toaster::destroyed', toaster => { /* istanbul ignore next: hard to test */ - if (toaster === self.toaster) { + if (toaster === this.toaster) { handleDestroy() } }) diff --git a/src/components/tooltip/helpers/bv-popper.js b/src/components/tooltip/helpers/bv-popper.js index 2cace4baa7b..16a9900a84b 100644 --- a/src/components/tooltip/helpers/bv-popper.js +++ b/src/components/tooltip/helpers/bv-popper.js @@ -7,7 +7,7 @@ import Vue from '../../../utils/vue' import Popper from 'popper.js' -import { getCS, select } from '../../../utils/dom' +import { getCS, requestAF, select } from '../../../utils/dom' import { toFloat } from '../../../utils/number' import { HTMLElement, SVGElement } from '../../../utils/safe-types' import { BVTransition } from '../../../utils/bv-transition' @@ -139,12 +139,19 @@ export const BVPopper = /*#__PURE__*/ Vue.extend({ this.$on('show', el => { this.popperCreate(el) }) - // Self destruct once hidden - this.$on('hidden', () => { - this.$nextTick(this.$destroy) - }) - // If parent is destroyed, ensure we are destroyed - this.$parent.$once('hook:destroyed', this.$destroy) + // Self destruct handler + const handleDestroy = () => { + this.$nextTick(() => { + // In a `requestAF()` to release control back to application + requestAF(() => { + this.$destroy() + }) + }) + } + // Self destruct if parent destroyed + this.$parent.$once('hook:destroyed', handleDestroy) + // Self destruct after hidden + this.$once('hidden', handleDestroy) }, beforeMount() { // Ensure that the attachment position is correct before mounting diff --git a/src/components/tooltip/helpers/bv-tooltip.js b/src/components/tooltip/helpers/bv-tooltip.js index 6f6c9693930..a530d198fba 100644 --- a/src/components/tooltip/helpers/bv-tooltip.js +++ b/src/components/tooltip/helpers/bv-tooltip.js @@ -21,6 +21,7 @@ import { isElement, isVisible, removeAttr, + requestAF, select, setAttr } from '../../../utils/dom' @@ -228,7 +229,14 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({ // Destroy ourselves when the parent is destroyed if (this.$parent) { - this.$parent.$once('hook:beforeDestroy', this.$destroy) + this.$parent.$once('hook:beforeDestroy', () => { + this.$nextTick(() => { + // In a `requestAF()` to release control back to application + requestAF(() => { + this.$destroy() + }) + }) + }) } this.$nextTick(() => {