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

能否不使用<template>与插槽为自定义元素添加子元素?

实现无需手动写模板/插槽的可容纳子元素的自定义Web组件

你之前的代码拿不到子元素是因为:自定义元素的子元素属于Light DOM(也就是<side-menu>标签包裹的内容),而你在connectedCallback里查询的是Shadow DOM内部.menu的子元素——这是两个完全独立的DOM树,所以返回空NodeList是正常的。

要让自定义元素像<ul>容纳<li>那样直接接受子元素,最标准且简洁的方式是使用Web组件的默认插槽,不需要用户在使用组件时额外写<template>或插槽模板,只需要在组件内部的Shadow DOM中添加<slot>标签即可,它会自动把Light DOM的子元素插入到对应位置。

修改后的完整代码

JavaScript部分

class SideMenu extends HTMLElement {
    constructor() {
        super();
        this.shadow = this.attachShadow({mode:'open'});
    }

    render() {
        this.shadow.innerHTML = `
        <style>
          .menu {
            display: flex;
            flex-direction: column;
            height: 100vh;
            padding: 2em;
            width: 33vw;
            gap: 10px;
            background-color: #2C2B2B;
          }
          /* 给插槽内的子元素设置样式,使用::slotted()伪元素 */
          .menu ::slotted(*) {
            color: white;
            padding: 8px;
            border-radius: 4px;
            background-color: #3A3939;
            cursor: pointer;
          }
        </style>
        <div class="menu">
          <!-- 默认插槽:自动插入所有Light DOM子元素 -->
          <slot></slot>
        </div>
        `;
    }

    connectedCallback() {
        this.render();
        // 获取组件的子元素,直接查询自定义元素本身(Light DOM)
        const menuItems = this.children;
        console.log('当前菜单子元素:', menuItems);
    }
}

customElements.define('side-menu', SideMenu);

HTML使用方式

和你原来的写法完全一致,不需要额外模板:

<side-menu>
    <div>Element1</div>
    <div>Element2</div>
    <div>Element3</div>
    <div>ElementN</div>
</side-menu>

关键说明

  • 默认插槽<slot>是Web组件规范的原生特性,会自动接收所有未指定插槽名的Light DOM子元素,完全满足你“像ul/li那样直接使用”的需求。
  • 由于Shadow DOM的样式隔离特性,要给插槽内的子元素设置样式,必须使用::slotted()伪元素,它可以选中插槽内的顶层元素。
  • 如果需要获取子元素,不要去Shadow DOM里查询,直接通过this.children或this.querySelectorAll('*')操作自定义元素本身即可,这些是Light DOM中的子元素。

内容的提问来源于stack exchange,提问作者Victor Santizo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:54:24