Javascript 在照明元素上实现外部单击
我正在使用LitElements制作一个自定义下拉web组件,在实现click outside dropwdown to close功能时,我注意到一些意外的行为阻碍了我。在下面的Javascript 在照明元素上实现外部单击,javascript,typescript,lit-element,lit-html,Javascript,Typescript,Lit Element,Lit Html,我正在使用LitElements制作一个自定义下拉web组件,在实现click outside dropwdown to close功能时,我注意到一些意外的行为阻碍了我。在下面的async firstUpdated()函数中,我将作为创建事件侦听器。注销下拉列表按预期工作,但注销目标每次都返回根…元素,虽然在一定程度上是准确的,但不够具体。如果有更好的方法来处理外部点击事件,我洗耳恭听 作为参考,这里有一些我正在尝试复制的已经构建的东西(尽管源代码是隐藏的): async firstUpdat
async firstUpdated()
函数中,我将作为创建事件侦听器。注销下拉列表
按预期工作,但注销目标
每次都返回根…
元素,虽然在一定程度上是准确的,但不够具体。如果有更好的方法来处理外部点击事件,我洗耳恭听
作为参考,这里有一些我正在尝试复制的已经构建的东西(尽管源代码是隐藏的):
async firstUpdated(){
等待新承诺((r)=>setTimeout(r,0));
this.addEventListener('click',event=>{
const dropdown=this.shadowRoot?.getElementById('dropdown-select');
const target=event.target;
如果(!dropdown?.contains(目标)){
console.log('im-out');
}
});
}
@customElement(“自定义下拉列表”)
public render():TemplateResult{
返回html`
${this.value}
${this.dropdownItems(this.options)}
`;
}
的目标
属性设置为
最顶端的事件目标必须是渲染顺序中最高的元素,该元素能够成为一个事件目标
因为影子DOM封装了它的内部结构,所以事件是。在您的示例中,单击
事件的目标
被重新定位到自定义下拉列表
,因为这是能够成为目标的第一个也是最高的元素
如果需要针对自定义元素中的元素,可以采用以下方法之一:
下面是一个我相信您正在寻找的功能示例。如果单击
自定义元素
,它将切换其活动状态(类似于切换下拉列表)。如果单击页面上的任何其他元素,自定义元素将自动停用(类似于在失去焦点时隐藏下拉列表)
//定义自定义元素类型
类MySpan扩展了HTMLSpanElement{
构造函数(){
超级();
this.attachShadow({mode:'open'});
常量文本='自定义元素';
const style=document.createElement('style');
style.textContent=`
跨度{
填充物:5px;
保证金:5px;
背景颜色:灰色;
颜色:白色;
}
.主动{
背景颜色:浅绿色;
颜色:黑色;
}
`;
this.span=document.createElement('span');
this.span.innerText=文本;
this.span.addEventListener('单击',(事件)=>{
log('自定义元素:在自定义元素内单击');
这是一个“handleClick”(事件);
});
this.shadowRoot.append(样式,this.span);
}
handleClick(事件){
//如果事件来自内部事件侦听器,
//目标将是我们的span元素,我们可以切换它。
//如果事件来自元素外部,
//目标不能是我们的span元素,我们应该
//去激活它。
if(event.target==this.span){
this.span.classList.toggle('active');
}
否则{
this.span.classList.remove('active');
}
}
}
define('my-span',MySpan,{extends:'span});
//插入自定义元素的实例
const div1=document.querySelector('#target');
const mySpan=新mySpan();
第1部分:儿童(mySpan);
//将事件侦听器添加到页面
函数handleClick(事件){
//如果我们没有单击自定义元素,就让它
//了解事件,以便可以停用其范围。
如果(event.target!==mySpan){
log(`PAGE:单击${event.target}。通知自定义元素。`);
mySpan.handleClick(事件);
}
}
document.body.addEventListener('click',(事件)=>handleClick(事件))代码>
p{
填充物:5px;
背景颜色:浅灰色;
}
这是一个段落
这是第二段
这是第三段
这是第四段。
好的,后续问题。。。比如说,我一直在关注页面上任何地方的点击,而不仅仅是在影子DOM中。那可能吗?我能够让合成路径位工作,但它只在单击阴影DOM内部时触发。我在帖子中添加了一个例子,希望能更好地解释。当然,这是可能的。我在自定义元素中添加了一个事件监听器示例,用于处理直接交互,以及一个页面范围的事件监听器,用于将外部事件传播到自定义元素中。感谢这个示例,它并不完全匹配,但我能够将您的一些输入拼凑起来,以获得一个工作示例。
async firstUpdated() {
await new Promise((r) => setTimeout(r, 0));
this.addEventListener('click', event => {
const dropdown = <HTMLElement>this.shadowRoot?.getElementById('dropdown-select');
const target = <HTMLElement>event.target;
if (!dropdown?.contains(target)) {
console.log('im outside');
}
});
}
@customElement('custom-drop-down')
public render(): TemplateResult {
return html`
<div>
<div id="dropdown-select" @action=${this.updateValue}>
<div class="current-selection" @click=${this.toggleDropdown}>
${this.value}
</div>
<div class="dropdown-options" id="dropdown-options">
${this.dropdownItems(this.options)}
</div>
</div>
</div>
`;
}