[英]querySelectorAll not selecting elements within shadowRoot
我正在尝试使用Webpack和Web Component创建井字游戏。
我需要 select div
标签在place-mark
组件处的shadowRoot
内具有cell
class 然后根据另一个 function 计算的 Turn 将innerText
更新为 O/X。
逻辑运行正常,但我不能 select 正确的组件来更新 HTML 视图,以便用户可以看到所选区域的当前状态。
这是我简化的 HTML 代码:
<div class="board" id="board">
<place-mark data-cell></place-mark>
</div>
这是我的简化组件代码:
const template = document.createElement("template");
template.innerHTML = `<div class="cell" />`;
export default class PlaceMark extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));}}
window.customElements.define("place-mark", PlaceMark);
这是我的简化 JS 代码:
const X_CLASS = "x";
const CIRCLE_CLASS = "circle";
const cellElements = document.querySelectorAll('[data-cell]');
const board = document.getElementById("board");
let circleTurn;
function startGame() {
cell.addEventListener("click", handleClick, { once: true });});
}
function handleClick(e) {
const cell = e.target;
const currentClass = circleTurn ? CIRCLE_CLASS : X_CLASS;
placeMark(cell, currentClass);
if (checkWin(currentClass)) {
endGame(false);
} else if (isDraw()) {
endGame(true);
} else {
swapTurns();
setBoardHoverClass();
}
}
function placeMark(cell, currentClass) {
cell.classList.add(currentClass);
}
如果您需要以上代码的完整版本,这是我的项目:
你可以简单地从你的代码中删除shadowRoot
它将使您有机会访问所有元素并querySelect
选择您想要的内容。
export default class PlaceMark extends HTMLElement {
constructor() {
super();
this.appendChild(template.content.cloneNode(true));}}
window.customElements.define("place-mark", PlaceMark);
全局querySelector
代码无法访问shadowRoots中的 DOM 内容。
如果你有一个open
的 shadowRoot,你可以这样做:
document.querySelector("my-component").shadowRoot("[data-cell]")
当您嵌套了 shadowRoots 时,这当然会变得棘手。
您可能希望将逻辑更改为:
下面的工作SO片段:
tileclicked
事件<my-board>
监听这个事件colortile
colortile
事件 <my-board></my-board> <hr> <my-board></my-board> <script> class GameComponent extends HTMLElement { constructor(html){ super().attachShadow({mode: "open"}).innerHTML = html; } dispatch({ from = this,eventname,detail = {} }) { from.dispatchEvent(new CustomEvent(eventname, { composed: true, bubbles: true, detail })); } listen({at = this,eventname,func }) { at.addEventListener(eventname, func); } } customElements.define("my-board", class extends GameComponent { constructor() { super(`<style>:host{display:grid;grid:repeat(3,20px)/repeat(3,60px);gap:1px}</style>` + "green,red,blue,orange,olive,tan,teal,yellow,lime".split(",").map(color => `<my-tile>${color}</my-tile>`).join("")); } connectedCallback() { this.listen({ at:this, eventname:"tileclicked", func: (evt) => { //console.log(evt.target,evt.composedPath()); this.dispatch({ from: this, eventname: "colortile", detail: { color: evt.detail.color }})}}) } }); customElements.define("my-tile", class extends GameComponent { constructor() { super(`<style>:host{text-align:center;cursor:pointer}</style><slot></slot>`); } connectedCallback() { this.onclick = () => this.dispatch({ from: this, eventname: "tileclicked", detail: { color: this.innerText }}); this.listen({ at: this.getRootNode().host.closest("my-board"), eventname: "colortile", func: (evt) => this.style.background = evt.detail.color }); } }); </script>
游乐场: https://jsfiddle.net/WebComponents/Lk9r4gx2/
笔记:
实际上,我不会在<my-tile>
上设置 shadowDOM; 然后<my-board>
STYLE 可以设置所有图块的样式
您也不需要getRootNode()
来逃避shadowRoot,并找到closest("my-board")
尝试禁用的console.log
以了解事件如何重新定位,然后composedPath
会保存您的...
它的 JavaScript,您可以传递 Function参考detail:{}
属性包...这样 Tile 可以访问板上的方法,反之亦然。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.