在 Web 组件中获取事件目标
Get event target inside a web component
锚元素 (<a>
) 是在用户与网络组件交互时创建的。问题是,当单击锚点时,我无法从 Web 组件的“外部”获取返回的锚点元素。
我添加了一个事件监听器 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>
ShadowDOM的目的正是屏蔽ShadowHTML的内容DOM 从容器的角度来看。
这也是为什么重新定位内部事件以暴露 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()
。
锚元素 (<a>
) 是在用户与网络组件交互时创建的。问题是,当单击锚点时,我无法从 Web 组件的“外部”获取返回的锚点元素。
我添加了一个事件监听器 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>
ShadowDOM的目的正是屏蔽ShadowHTML的内容DOM 从容器的角度来看。
这也是为什么重新定位内部事件以暴露 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()
。