anchor 元素 ( <a>
) 是在用户与网络组件交互时创建的。问题是,当单击 anchor 时,我无法从 Web 组件的“外部”获取返回的 anchor 元素。
我向 document
添加了一个事件监听器监听点击事件。当单击 DOM 中某处的元素时,我期望 e.target
成为被点击的元素。
在 Web 组件内某处单击的情况下,将返回自定义元素 ( <fancy-list></fancy-list>
),而不是单击的元素。
当影子DOM的模式设置为open
时DOM 应该是可访问的。
class Fancylist extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const wrapper = document.createElement('div');
wrapper.innerHTML = `<ul></ul><button>Add item</button>`;
shadow.appendChild(wrapper);
this.on_root_click = this.on_root_click.bind(this);
}
connectedCallback() {
this.ul_elm = this.shadowRoot.querySelector('ul');
this.shadowRoot.addEventListener('click', this.on_root_click, false);
}
on_root_click(e){
switch(e.target.nodeName){
case 'BUTTON':
this.ul_elm.innerHTML += '<li><a href="p1">List item</a></li>';
break;
case 'A':
e.preventDefault();
console.log('You clicked a link!');
break;
}
}
}
customElements.define('fancy-list', Fancylist);
<!DOCTYPE html>
<html>
<head>
<title>List</title>
<meta charset="utf-8" />
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', e => {
document.body.addEventListener('click', e => {
//console.log(e.composedPath());
console.log(e.target); // why is this not returning an anchor element when an anchor is clickend inside the <fancy-list>?
}, false);
}, false);
</script>
</head>
<body>
<h1>List</h1>
<fancy-list></fancy-list>
</body>
</html>
最佳答案
Shadow DOM 的目的正是从容器的 Angular 屏蔽 Shadow DOM 的 HTML 内容。
这也是为什么重新定位内部事件以暴露 Shadow DOM 宿主的原因。
但是,您仍然可以通过获取 Event.path
数组属性的第一项来获取真正的目标。
event.path[0]
注意:当然它只适用于open
Shadow DOM。
class Fancylist extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const wrapper = document.createElement('div');
wrapper.innerHTML = `<ul></ul><button>Add item</button>`;
shadow.appendChild(wrapper);
this.on_root_click = this.on_root_click.bind(this);
}
connectedCallback() {
this.ul_elm = this.shadowRoot.querySelector('ul');
this.shadowRoot.addEventListener('click', this.on_root_click, false);
}
on_root_click(e){
switch(e.target.nodeName){
case 'BUTTON':
this.ul_elm.innerHTML += '<li><a href="p1">List item</a></li>';
break;
case 'A':
e.preventDefault();
break;
}
}
}
customElements.define('fancy-list', Fancylist);
<!DOCTYPE html>
<html>
<head>
<title>List</title>
<meta charset="utf-8" />
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', e => {
document.body.addEventListener('click', e => {
console.log(e.path[0]);
}, false);
}, false);
</script>
</head>
<body>
<h1>List</h1>
<fancy-list></fancy-list>
</body>
</html>
2021 年更新
如评论所述,您现在应该使用 event.composedPath()
。
关于javascript - 在 Web 组件中获取事件目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57963312/