【问题标题】:How to get HTMLElement from child component in slot?如何从插槽中的子组件获取 HTMLElement?
【发布时间】:2021-07-29 09:17:38
【问题描述】:

如何在 slot 中获取子元素的 Dom 元素。尝试在生命钩子onMounted()中获取对象的el vnode属性为null

我的组件:

<template>
   <div>{{text}}</div>
   <slot></slot>
</template>

<script lang="ts">
import { defineComponent, onMounted } from "vue";

export default defineComponent({
    name: "my-component",
    props: {
        text: {
            type: String,
            default: '',
            required: true,
        },
    },
    setup( _, ctx) {
        
        onMounted( () => {
            if (ctx.slots.default) {
                console.log( (ctx.slots.default()[0]) ); // <- property "el" - is null
            }
        })

    },
});
</script>

【问题讨论】:

    标签: vue.js vuejs3


    【解决方案1】:

    要记住的几件事(对于其他希望这样做的人)

    • ✅slots 对象是通过第二个参数的上下文传入的
    • ✅ 默认访问未命名的插槽内容
    • slots.default是需要执行的函数
    • slots.default()返回一个数组,因为一个槽可以有多个元素,在大多数情况下你可以选择[0]
    • ❌ 内容仅在组件渲染后可用。在示例中,我使用了onMounted,这可能是最简单的。
    • ? 但是,如果传递的元素是 Vue 组件,则该元素根本不可用

    插槽可通过函数slots.default() 访问,该函数采用用于呈现插槽的数据参数。如果您想使用渲染功能,这对于生成节点可能很有用,并且在很大程度上似乎只是一些暴露的内部结构。

    我发现了一些技巧来解决它使用节点遍历。

    一个(可能是更好的选择)使用子对象 (slots.default()[0].children.default()[0].el.parentElement)

    另一个使用refnextElementSibling

    这个想法是您放置一个跨度(或其他一些“不可见”元素),您可以使用ref 获得参考。然后在 onMounted 处理程序中,您可以使用该元素获取将成为下一个元素兄弟的 slot 元素。

    var app = Vue.createApp({
      setup() {return {}}
    });
    
    app.component("parent-component", {
      template: `<div>?<span ref="slotRef"></span><slot></slot></div>`,
      setup(props, ctx) {
        const slotRef = Vue.ref(null); // create a ref
        Vue.onMounted(()=>{
          const defaultSlot = ctx.slots.default();
          console.log(defaultSlot[0].children.default()[0].el.parentElement) // or get the parent of the first child
          defaultSlot[0].children.default()[0].el.parentElement.innerText += "?"
          console.log(slotRef.value.nextElementSibling); // get the Sibling of ref
          slotRef.value.nextElementSibling.innerText += "?"
        })
        return {slotRef};
      }
    });
    app.component("child-component", {
      template: `<div>?<slot></slot></div>`,
    });
    
    app.mount("#app");
    div{border:1px solid; padding:2px;}
    <script src="https://unpkg.com/vue@3.0.11/dist/vue.global.prod.js"></script>
    <div id="app">
      <parent-component>
        <child-component>
          ?
        </child-component>
      </parent-component>
    </div>

    【讨论】:

    • 我需要得到一个子组件的父元素&lt;my-component&gt; &lt;child-component/&gt; &lt;/my-component&gt;
    • 只使用 slot 元素的父节点。像这样:defaultSlot[0].el.parentNode
    • 如果 el 为空,我无法获取 parentNode... 示例 codesandbox.io/s/beautiful-hermann-1x4bp?file=/src/components/…
    • 我现在明白了,我的错。不幸的是,如果作为插槽传递的元素是一个组件,则 $el 不可用,但我已经用一些技巧更新了答案以获取元素
    • 另外,查看这个使用渲染函数的示例和withDirectives jsfiddle.net/skirtle/rsnLda05 以获得另一个选项
    猜你喜欢
    • 2012-04-01
    • 2021-12-02
    • 2022-06-29
    • 2018-04-25
    • 2021-02-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多