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

JavaScript实例化自定义内置元素失效问题排查

问题分析与修复

你开发的递归自定义内置元素,HTML初始化的实例能正常工作,但JavaScript生成的子元素无法继承自定义特性,核心问题出在自定义内置元素的创建方式,和页面生命周期关联不大,具体原因及修复方案如下:

核心问题点

  1. 自定义内置元素创建错误:
    你通过document.createElement('ul')后再设置is属性的方式,无法将普通<ul>升级为test-list自定义元素实例,它仍然是原生HTMLUListElement,自然没有你定义的data setter和render方法。

  2. 递归数据赋值逻辑错误:
    你在render方法里给子列表赋值newlist.data = data;,这里的data是全局变量,而非当前元素的element.data,会导致所有子列表重复渲染全局数据,逻辑完全错误。

修复后的代码

HTML代码(无需修改)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <ul is="test-list" id="testList">

    </ul>
    <script type="module" src="/js/test-list-element.js"></script>

    <script>
        let data = [
            {
                name: 'a',
                data: [{
                    name: 'a',
                    data: []
                },
                {
                    name: 'b',
                    data: []
                },
                {
                    name: 'c',
                    data: []
                },
                {
                    name: 'd',
                    data: []
                }]
            },
            {
                name: 'b',
                data: [{
                    name: 'a',
                    data: []
                },
                {
                    name: 'b',
                    data: []
                },
                {
                    name: 'c',
                    data: []
                },
                {
                    name: 'd',
                    data: []
                }]
            },
            {
                name: 'c',
                data: [{
                    name: 'a',
                    data: []
                },
                {
                    name: 'b',
                    data: []
                },
                {
                    name: 'c',
                    data: []
                },
                {
                    name: 'd',
                    data: []
                }]
            },
            {
                name: 'd',
                data: [{
                    name: 'a',
                    data: []
                },
                {
                    name: 'b',
                    data: []
                },
                {
                    name: 'c',
                    data: []
                },
                {
                    name: 'd',
                    data: []
                }]
            },
        ];

        window.onload = (event) => {
            let listElement = document.getElementById("testList");
            listElement.data = data;
        }
    </script>

</body>

</html>

修复后的test-list-element.js

class testList extends HTMLUListElement {
    constructor() {
      super();
      this.render = this.render.bind(this);
    }
  
    #data = null;
    set data(value) {
      this.#data = value;
      this.render();
    }

    render(){
        if(!this.#data) return;

        this.#data.forEach(element => {
            let newItem = document.createElement('li');
            newItem.innerText = element.name;
            this.appendChild(newItem);

            // 增加子数组长度判断,避免空数组创建空列表
            if(element.data && element.data.length > 0)
            {
                // 正确创建自定义内置元素的方式
                let newlist = document.createElement('ul', { is: 'test-list' });          
                // 赋值当前元素的子数据,而非全局data
                newlist.data = element.data;
                newItem.appendChild(newlist);
            }
        });
    }
}

customElements.define('test-list', testList, { extends: 'ul' });

补充说明

  • 继承原生HTML元素的自定义内置元素,必须通过document.createElement(tagName, { is: 'custom-tag-name' })的方式创建,才能得到自定义元素实例。
  • 递归渲染时要严格使用当前节点的子数据,避免引用全局变量导致逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:33:30