mic*_*ael 3 javascript event-delegation web-component shadow-dom
我当前的项目使用 Web 组件(自定义元素和 Shadow DOM),这使我能够封装复杂的逻辑和样式,远离 Light DOM。
不幸的是,我现在遇到了一个障碍,我需要能够随意切换元素,而无需解除绑定和重新绑定事件处理程序的麻烦。
对我来说,这听起来像是事件委托的工作,因此我尝试向 Light DOM 中的父节点添加一个事件侦听器,希望该事件能够从 Shadow DOM 中冒出。
这似乎违背了 Shadow DOM 的封装,并且 event.target 始终是 ShadowRoot 而不是子级。
在这种情况下我可以做些什么来允许经典事件委托吗?下面的代码片段显示了问题。我希望能够单击内部 DIV 并在单击事件处理程序中处理单击,但 event.target 始终是 custom-el
/* jshint esversion: 6 */
customElements.define('custom-el', class extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({
mode: 'open'
});
const oInnerDiv = document.createElement('div');
oInnerDiv.classList.add('inner');
oInnerDiv.style.border = '2px solid blue';
oInnerDiv.style.padding = '3rem';
this._shadowRoot.appendChild(oInnerDiv);
}
});
document.addEventListener('click', oEvent => {
document.getElementById('result').innerText = oEvent.target.tagName;
}, true);Run Code Online (Sandbox Code Playgroud)
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
}
main,
div,
custom-el {
display: inline-block;
border: 2px solid black;
padding: 3rem;
}Run Code Online (Sandbox Code Playgroud)
<main>
<custom-el>
</main>
<p id="result"></p>Run Code Online (Sandbox Code Playgroud)
如果shadow DOM模式为open,则可以借助该Event.composedPath()方法获取单击的内部元素,该方法将返回交叉节点的数组(首先是内部节点)。
document.addEventListener('click', oEvent => {
result.innerText = oEvent.composedPath()[0].tagName;
}, true);
Run Code Online (Sandbox Code Playgroud)
此方法替换旧Event.path属性。
document.addEventListener('click', oEvent => {
result.innerText = oEvent.composedPath()[0].tagName;
}, true);
Run Code Online (Sandbox Code Playgroud)
customElements.define('custom-el', class extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({ mode: 'open' });
const oInnerDiv = document.createElement('div');
oInnerDiv.classList.add('inner');
oInnerDiv.style.border = '2px solid blue';
oInnerDiv.style.padding = '1rem';
this._shadowRoot.appendChild(oInnerDiv);
}
});
document.addEventListener('click', oEvent => {
result.innerText = oEvent.composedPath()[0].tagName;
});Run Code Online (Sandbox Code Playgroud)
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
margin: 0;
padding: 0;
}
main,
div,
custom-el {
display: inline-block;
border: 2px solid black;
padding: 1rem;
}Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1274 次 |
| 最近记录: |