🌐 AI搜索 & 代理 主页
Skip to content

Commit fe13503

Browse files
committed
fix(vue3): do not rely on __vueParentComponent in tooltip
1 parent d8edafc commit fe13503

File tree

8 files changed

+63
-14
lines changed

8 files changed

+63
-14
lines changed

src/components/link/link.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { isBoolean, isEvent, isFunction, isUndefined } from '../../utils/inspect
1414
import { omit, sortKeys } from '../../utils/object'
1515
import { makeProp, makePropsConfigurable, pluckProps } from '../../utils/props'
1616
import { computeHref, computeRel, computeTag, isRouterLink } from '../../utils/router'
17-
import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode'
1817
import { attrsMixin } from '../../mixins/attrs'
1918
import { listenOnRootMixin } from '../../mixins/listen-on-root'
2019
import { listenersMixin } from '../../mixins/listeners'
@@ -165,9 +164,11 @@ export const BLink = /*#__PURE__*/ Vue.extend({
165164
} else {
166165
// Router links do not emit instance `click` events, so we
167166
// add in an `$emit('click', event)` on its Vue instance
167+
//
168+
// seems not to be required for Vue3 compat build
168169
/* istanbul ignore next: difficult to test, but we know it works */
169-
if (isRouterLink && getInstanceFromVNode(event.currentTarget)) {
170-
getInstanceFromVNode(event.currentTarget).$emit(EVENT_NAME_CLICK, event)
170+
if (isRouterLink) {
171+
event.currentTarget.__vue__?.$emit(EVENT_NAME_CLICK, event)
171172
}
172173
// Call the suppliedHandler(s), if any provided
173174
concat(suppliedHandler)

src/components/modal/modal.spec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { createWrapper, mount } from '@vue/test-utils'
22
import { isVue3 } from '../../vue'
3-
import { waitNT, waitRAF } from '../../../tests/utils'
4-
import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode'
3+
import { waitNT, waitRAF, getInstanceFromVNode } from '../../../tests/utils'
54
import { BModal } from './modal'
65
import { BvModalEvent } from './helpers/bv-modal-event.class'
76

src/components/tooltip/helpers/bv-tooltip.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
} from '../../../constants/events'
2525
import { useParentMixin } from '../../../mixins/use-parent'
2626
import { arrayIncludes, concat, from as arrayFrom } from '../../../utils/array'
27-
import { getInstanceFromVNode } from '../../../utils/get-instance-from-vnode'
27+
import { getInstanceFromElement } from '../../../utils/element-to-vue-instance-registry'
2828
import {
2929
attemptFocus,
3030
closest,
@@ -796,8 +796,10 @@ export const BVTooltip = /*#__PURE__*/ Vue.extend({
796796
// Dropdown shown and hidden events will need to emit
797797
// Note: Dropdown auto-ID happens in a `$nextTick()` after mount
798798
// So the ID lookup would need to be done in a `$nextTick()`
799-
if (getInstanceFromVNode(target)) {
800-
getInstanceFromVNode(target)[on ? '$on' : '$off'](EVENT_NAME_SHOWN, this.forceHide)
799+
const instance = getInstanceFromElement(target)
800+
801+
if (instance) {
802+
instance[on ? '$on' : '$off'](EVENT_NAME_SHOWN, this.forceHide)
801803
}
802804
},
803805
// --- Event handlers ---

src/components/transporter/transporter.spec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { isVue3 } from '../../vue'
22
import { mount } from '@vue/test-utils'
3-
import { waitNT } from '../../../tests/utils'
4-
import { getInstanceFromVNode } from '../../utils/get-instance-from-vnode'
3+
import { waitNT, getInstanceFromVNode } from '../../../tests/utils'
54
import { BVTransporter } from './transporter'
65

76
describe('utils/transporter component', () => {

src/mixins/dropdown.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ import { clickOutMixin } from './click-out'
3737
import { focusInMixin } from './focus-in'
3838
import { idMixin, props as idProps } from './id'
3939
import { listenOnRootMixin } from './listen-on-root'
40+
import {
41+
registerElementToInstance,
42+
removeElementToInstance
43+
} from '../utils/element-to-vue-instance-registry'
4044

4145
// --- Constants ---
4246

@@ -181,11 +185,15 @@ export const dropdownMixin = Vue.extend({
181185
this.whileOpenListen(false)
182186
this.destroyPopper()
183187
},
188+
mounted() {
189+
registerElementToInstance(this.$el, this)
190+
},
184191
beforeDestroy() {
185192
this.visible = false
186193
this.whileOpenListen(false)
187194
this.destroyPopper()
188195
this.clearHideTimeout()
196+
removeElementToInstance(this.$el)
189197
},
190198
methods: {
191199
// Event emitter
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { isVue3 } from '../vue'
2+
3+
let registry = null
4+
if (isVue3) {
5+
registry = new WeakMap()
6+
}
7+
8+
export const registerElementToInstance = (element, instance) => {
9+
if (!isVue3) {
10+
return
11+
}
12+
13+
registry.set(element, instance)
14+
}
15+
16+
export const removeElementToInstance = element => {
17+
if (!isVue3) {
18+
return
19+
}
20+
21+
registry.delete(element)
22+
}
23+
24+
export const getInstanceFromElement = element => {
25+
if (!isVue3) {
26+
return element.__vue__
27+
}
28+
29+
let currentElement = element
30+
31+
while (currentElement) {
32+
if (registry.has(currentElement)) {
33+
return registry.get(currentElement)
34+
}
35+
currentElement = currentElement.parentNode
36+
}
37+
38+
return null
39+
}

src/utils/get-instance-from-vnode.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

tests/utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { isVue3 } from '../src/vue'
2+
13
// --- Utils for testing ---
24

35
export const wrapWithMethods = (Component, methods) => ({
@@ -14,3 +16,6 @@ export const wrapWithMethods = (Component, methods) => ({
1416

1517
export const waitNT = ctx => new Promise(resolve => ctx.$nextTick(resolve))
1618
export const waitRAF = () => new Promise(resolve => requestAnimationFrame(resolve))
19+
20+
export const getInstanceFromVNode = vnode =>
21+
isVue3 ? vnode.__vueParentComponent.ctx : vnode.__vue__

0 commit comments

Comments
 (0)