customelements.define() 仅注册元素类型,不自动插入节点;必须先调用 define 注册,再用 createelement 创建实例,最后通过 appendchild 等方法插入 dom 才能触发生命周期。

customElements.define() 只注册元素类型,不自动插入节点;真正插入 DOM 必须像普通元素一样用 document.createElement() 创建实例,再通过 appendChild()、insertBefore() 或 insertAdjacentHTML() 挂载。
自定义元素必须先 define 再 createElement
浏览器不认识 <my-button></my-button> 这种标签,直接写在 HTML 里或用 innerHTML 插入会当普通未知标签处理(不触发生命周期,无样式/行为)。必须先调用 customElements.define('my-button', MyButtonClass) 注册构造器,之后才能用 document.createElement('my-button') 创建合法实例。
常见错误:只 define 没 createElement,页面空白无报错;或 define 前就 createElement,返回的是普通 HTMLUnknownElement,connectedCallback 不执行。
-
customElements.get('my-button')返回undefined表示未注册成功(比如名字含大写字母、没加短横线) - 重复 define 同一名字会抛
Failed to execute 'define' on 'CustomElementRegistry': the name "xxx" has already been used - 注册后创建的实例才是真正的自定义元素,能响应
attributeChangedCallback和属性变更
插入自定义元素节点和普通元素完全一样
创建好实例后,插入方式与 div、span 无异——appendChild()、insertBefore()、insertAdjacentHTML() 都可用,但要注意语义和副作用:
- 用
appendChild(myBtn)插到容器末尾,触发connectedCallback - 用
parent.insertBefore(myBtn, refEl)插到指定位置前,refEl必须是parent的直接子节点 - 用
parent.insertAdjacentHTML('beforeend', '<my-button label="提交"></my-button>')可一次性插入多个,但注意:字符串中的属性值全是字符串,不会触发attributeChangedCallback,且若未提前 define 会变成未知标签
插入后不生效?检查 connectedCallback 是否被调用
自定义元素只有挂载进真实 DOM 才会触发 connectedCallback。如果插入后没反应,先确认:
- 父容器已存在且非
null(避免Cannot read property 'appendChild' of null) - 操作在
DOMContentLoaded之后,或确保父节点已渲染 -
connectedCallback里是否用了this.shadowRoot却忘了this.attachShadow({ mode: 'open' }) - 是否误把自定义元素当函数调用:
new MyButtonClass()不等于document.createElement('my-button'),前者不进入 DOM 生命周期
批量插入或动态更新时别漏掉 Shadow DOM 和资源管理
自定义元素常配合 shadowRoot 封装样式和结构,但 appendChild() 插入的是 host 元素本身,不是 shadow 内容。容易混淆的点:
- 想往 shadow 内部追加节点,得先获取
this.shadowRoot,再对它调用appendChild() - 用
innerHTML +=往自定义元素内部拼接内容,会清空 shadowRoot 并破坏封装,应改用this.shadowRoot.appendChild() - 插入后需手动清理的资源(如定时器、事件监听)应在
disconnectedCallback中释放,否则切换路由时内存泄漏
define,而是它被插入 DOM 的那一刻——所有逻辑都围绕这个节点是否处于文档流中展开。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











