You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3如何在子组件内访问插槽根DOM元素以适配SortableJS

Vue3 中获取插槽根DOM元素适配SortableJS的实现方案

Vue2中我们可以直接将插槽第一个元素作为组件根节点,通过this.$el快速绑定SortableJS,实现代码如下:

export default { 
  render() {
    return this.$slots.default[0]
  },
  mounted() {
    Sortable.create(this.$el, {});
  }
}

Vue3中由于虚拟节点结构、插槽API和组件实例暴露规则的变化,直接调用this.$slots.default()[0]无法直接拿到目标DOM,普通模板ref也只能获取当前组件的外层容器,无法直接获取插槽内部的根元素。可以通过以下两种方案复现Vue2中的能力:

方案1:无额外外层容器实现(完全对齐Vue2用法)

直接通过插槽返回的虚拟节点获取真实DOM,跳过注释、碎片等非元素节点,兼容原生元素和自定义组件插槽场景:

选项API写法

import Sortable from 'sortablejs'
export default {
  mounted() {
    const slotVNodes = this.$slots.default()
    // 过滤获取第一个元素类型的虚拟节点
    const targetVnode = slotVNodes.find(vnode => vnode.type !== Symbol('v-fgt') && vnode.el?.nodeType === 1)
    if (!targetVnode) return
    // 插槽传入自定义组件时,取主动暴露的根元素,否则直接取vnode绑定的DOM
    const targetEl = targetVnode.component?.exposed?.rootEl || targetVnode.el
    Sortable.create(targetEl, {
      // 自定义Sortable配置
    })
  },
  render() {
    // 直接返回插槽内容,无额外DOM包裹
    return this.$slots.default()
  }
}

组合式API写法

<script setup>
import { useSlots, onMounted } from 'vue'
import Sortable from 'sortablejs'
const slots = useSlots()
onMounted(() => {
  const slotVNodes = slots.default()
  const targetVnode = slotVNodes.find(vnode => vnode.type !== Symbol('v-fgt') && vnode.el?.nodeType === 1)
  if (!targetVnode) return
  const targetEl = targetVnode.component?.exposed?.rootEl || targetVnode.el
  Sortable.create(targetEl, {
    // 自定义Sortable配置
  })
})
// 直接渲染插槽内容,无需外层容器
defineRender(() => slots.default())
</script>

如果插槽传入自定义组件,需要对应组件主动暴露内部根元素:defineExpose({ rootEl: 内部根元素的ref })

方案2:极简兼容方案(推荐)

新增外层容器设置display: contents,该属性会让容器不参与页面布局,视觉和结构上完全等价于直接绑定插槽根元素,代码更易维护:

<template>
  <div ref="sortableContainer" style="display: contents">
    <slot />
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import Sortable from 'sortablejs'
const sortableContainer = ref()
onMounted(() => {
  Sortable.create(sortableContainer.value, {
    // 自定义Sortable配置
  })
})
</script>

该方案不需要处理复杂的虚拟节点逻辑,也不会对原有页面样式结构产生任何影响,适配绝大多数场景。

内容的提问来源于stack exchange,提问作者Simon M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:09:01