如何正确访问自定义元素(Custom Element)的内部子元素?
错误原因
你的自定义元素没有开启Shadow DOM,不存在对应的根节点属性,所以访问.root会返回undefined,自然无法调用查询方法。你当前的实现是直接把内容写入了自定义元素的普通DOM树,没有做DOM隔离,不需要额外找根节点就能查询内部元素。
正确获取内部元素的方法
直接在选中的自定义元素实例上调用querySelector即可:
const navbar = document.querySelector('left-navbar'); const homeBtn = navbar.querySelector('#home-i'); homeBtn.addEventListener('click', () => { window.location.href = 'index.html'; changePageTitle(0); })
原有实现的优化建议
- 现有写法在
connectedCallback中直接赋值innerHTML,如果元素被多次移入DOM树,connectedCallback会重复触发,导致内容重复渲染,建议增加渲染判断:
class Navbar extends HTMLElement { connectedCallback() { // 避免重复渲染 if (this.isConnected && !this.querySelector('nav')) { this.innerHTML = ` <nav id='navbar'> <i class="fas fa-home" id='home-i'></i> <hr class="line"> <i class="fas fa-arrow-alt-circle-left" id='back-i'></i> <i class="fas fa-brain"></i> <i class="fas fa-lightbulb" id='quiz-i'></i> <i class="fas fa-sign-out-alt" id='exit-i'></i> </nav> ` } } } customElements.define('left-navbar', Navbar)
- 如果你需要做样式隔离,想要使用Shadow DOM,需要提前在构造函数中挂载Shadow Root:
class Navbar extends HTMLElement { constructor() { super(); // 开启Shadow DOM,mode设为open允许外部访问shadowRoot属性 this.attachShadow({mode: 'open'}); } connectedCallback() { if (this.isConnected && !this.shadowRoot.querySelector('nav')) { this.shadowRoot.innerHTML = ` <nav id='navbar'> <i class="fas fa-home" id='home-i'></i> <hr class="line"> <i class="fas fa-arrow-alt-circle-left" id='back-i'></i> <i class="fas fa-brain"></i> <i class="fas fa-lightbulb" id='quiz-i'></i> <i class="fas fa-sign-out-alt" id='exit-i'></i> </nav> ` } } } customElements.define('left-navbar', Navbar)
这种场景下获取内部元素的写法为:
const homeBtn = document.querySelector('left-navbar').shadowRoot.querySelector('#home-i');
- 额外注意:查询自定义元素内部节点的代码,必须要等
connectedCallback执行完成后再运行,否则可能还没渲染出对应节点,建议把相关逻辑放到DOMContentLoaded事件回调中,或者给JS文件添加defer属性。
内容的提问来源于stack exchange,提问作者Void
相关产品推荐
相关产品推荐

