如何在JavaScript中获取自定义HTMLElement的父元素或子元素?
自定义HTMLElement获取父元素、附加Canvas的解决方案
我是HTML、CSS和JavaScript新手,之前主要做C++和Java开发。现在想在自定义HTMLElement中获取父元素的尺寸和位置,还要给元素附加canvas,但试了多种方法都没成功,以下是我尝试的代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>360 Video Player Component</title> </head> <body> <!-- <script src="js/three.min.js"></script> --> <script type="text/javascript"> class threeSixtyVideoElement extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); console.log("hello"); if (this.parentElement != null) { console.log("parent = " + this.parentElement); } else { console.log("Bummer"); } } } window.customElements.define("threesixty-video", threeSixtyVideoElement); </script> <div class="firstLevelDiv" id="L1DIV1"> <div class="secondLevelDiv" id="L2DIV1"> <p>class=secondLevelDiv id=L2DIV1</p> </div> <threesixty-video class="secondLevelDiv" id="L2DIV2"></threesixty-video> <div class="secondLevelDiv" id="L2DIV3"> <p>class=secondLevelDiv id=L2DIV3</p> </div> </div> </body> </html>
问题原因
你的代码在constructor里获取parentElement会失败,因为自定义元素的constructor执行时,元素还没有被挂载到DOM树中,此时parentElement必然是null。
解决方法
使用自定义元素的connectedCallback生命周期钩子——这个方法会在元素被添加到DOM树后触发,此时可以安全地获取父元素、操作DOM:
修改后的完整代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>360 Video Player Component</title> <style> .secondLevelDiv { width: 400px; height: 300px; margin: 10px 0; border: 1px solid #ccc; } </style> </head> <body> <script type="text/javascript"> class threeSixtyVideoElement extends HTMLElement { constructor() { super(); // 创建shadow DOM,提前准备好canvas this.shadow = this.attachShadow({ mode: 'open' }); this.canvas = document.createElement('canvas'); // 给canvas加样式,默认占满自定义元素 this.canvas.style.width = '100%'; this.canvas.style.height = '100%'; this.canvas.style.display = 'block'; this.shadow.appendChild(this.canvas); } connectedCallback() { // 元素挂载到DOM后,获取父元素 const parent = this.parentElement; if (parent) { console.log('父元素:', parent); // 获取父元素的尺寸和位置 const parentRect = parent.getBoundingClientRect(); console.log('父元素尺寸:', `宽${parentRect.width}px,高${parentRect.height}px`); console.log('父元素位置:', `距离左边界${parentRect.left}px,距离顶部${parentRect.top}px`); // 让canvas尺寸匹配父元素(或者自定义元素自身,按需调整) this.canvas.width = parentRect.width; this.canvas.height = parentRect.height; } } } window.customElements.define("threesixty-video", threeSixtyVideoElement); </script> <div class="firstLevelDiv" id="L1DIV1"> <div class="secondLevelDiv" id="L2DIV1"> <p>class=secondLevelDiv id=L2DIV1</p> </div> <threesixty-video class="secondLevelDiv" id="L2DIV2"></threesixty-video> <div class="secondLevelDiv" id="L2DIV3"> <p>class=secondLevelDiv id=L2DIV3</p> </div> </div> </body> </html>
关键要点
- 生命周期钩子选择:
connectedCallback是处理DOM挂载后操作的正确时机,除了获取父元素,还可以在这里做事件监听、资源加载等操作。 - 尺寸获取:
getBoundingClientRect()能获取元素相对于视口的位置和精确尺寸,也可以用parent.offsetWidth/parent.offsetHeight获取元素的布局尺寸。 - Shadow DOM操作:canvas要附加到自定义元素的shadow DOM中,避免和外部DOM样式冲突,同时可以通过shadow DOM隔离组件内部样式。
内容的提问来源于stack exchange,提问作者Shaky
相关产品推荐
相关产品推荐

