需求
我是想实现一个 popover
组件,类似 Element UI 的 popover,使用的时候用 popover
组件包裹目标元素,在目标元素周围展示弹出内容。其中一个重点是想获取到目标元素相对屏幕的位置和宽高信息。
我看了下 Element UI
的 popover
组件也是这样实现的,和我的区别在于声明 slot
时使用的是旧版语法,也就是直接在元素上声明 slot
(具体代码见下面),我试了下这种语法确实是能通过 this.$slots?.xxx?.[0].elm
获取到 slot
元素的,但是目前 Vue 官方已经废弃了这种语法,新版语法读取到的 elm
是 undefined
。
大致代码如下:
<!-- popover 组件 -->
<template>
<span>
<div :style="position" class="common-popover-container" ref="popper">
</div>
<slot name="reference"></slot>
</span>
</template>
<!-- 组件使用 -->
<popover>
<!-- 新版语法 -->
<template v-slot:reference>
<button>在我周围显示弹出框</button>
</template>
<!-- Element 使用的旧语法 -->
<button slot="reference">在我周围显示弹出框</button>
</popover>
----------更新分割线-----------
问题
我可能没有表达清楚,我的结构是这样,声明一个组件 A
,A
组件接受一个具名 slot
,然后在 B
组件中使用 A
,需求是想在 A
中获取到 B
使用时给 A
传递的 slot
的相关信息。
这种跨组件的我了解到的好像没办法直接通过 ref
拿到对应元素,用官方推荐的 <template v-slot:xxx>
方式包裹的 slot
就无法读取 $slots
拿到对应的 elm,但是官方废弃的 <span slot="xxx">
语法包裹的 slot
可以通过读取 $slots
获取到 elm。
所以就想知道有没有什么官方推荐的解决办法。
大致代码如下:示例 demo
const A = {
mounted() {
this.$nextTick(() => {
console.log(this.$slots?.other?.[0].elm) // undefined
})
},
template: `
<div>
<slot name="other"></slot>
</div>
`
}
const B = {
components: {
A
},
template: `
<A>
<template v-slot:other>
<span ref="test">我是具名 slot</span>
</template>
</A>
`
}
----------原问题------------
如题,怎样能获得 Vue 组件中具名 slot 的 DOM 节点。
我试了下目前 Vue 支持的几种 slot 声明方式,发现之前的 <span slot="xxx">我是插槽</span>
的方式是可以拿到该插槽渲染的真实节点的,但是该语法已经被废弃,所以想问下在新的语法里面怎样能获得 Vue 组件中具名 slot 的 DOM 节点。具体情况见下面示例代码
我主要是通过这样获取到这个节点的位置和宽高信息。
示例代码
<template v-slot:xxx>
<span>我是插槽</span>
</template>
<!-- this.$slots.xxx?.[0]?.elm 是 undefined -->
<span slot="xxx">我是插槽</span>
<!-- this.$slots.xxx?.[0]?.elm 是该节点 -->
<span>我是默认插槽</span>
<!-- 不通过 template 包裹的默认插槽 -->
<!-- s.$slots.default?.[0]?.el 是该节点 -->
建议 popover 组件这样写:
就可以通过
this.$refs.reference
拿到 slot 里面内容的 dom 了。$scopeSlots 只能拿到 vnode,确实无法获取 dom。