微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Lit-Elements 上实现外部点击

如何解决在 Lit-Elements 上实现外部点击

我正在使用 LitElements 制作自定义下拉 Web 组件,在实现 click-outside-dropwdown-to-close 功能时,我注意到一些阻止我的意外行为。在 async firstUpdated() 函数下方,我将事件侦听器创建为 recommended in their documentation。注销 dropdown 按预期工作,但每次注销 target 都会返回根 <custom-drop-down>...</custom-drop-down> 元素,这在一定程度上虽然准确,但不够具体。如果有更好的方法来处理外部点击事件,我会全力以赴。

作为参考,这里有一些我正在尝试复制的已经构建的东西(虽然源代码是隐藏的):https://www.carbondesignsystem.com/components/dropdown/code/

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>
  `;
}

解决方法

click eventtarget 属性设置为 topmost event target

最上面的事件目标必须是呈现顺序中最高的元素,它可以是 event target

因为 shadow DOM 封装了它的内部结构,所以事件是 retargeted to the host element。在您的示例中,click 事件的 target 被重定向到 custom-drop-down,因为它是能够成为目标的第一个也是最高的元素。

如果您需要在自定义元素中定位一个元素,您可以采用以下方法之一:

  1. 在您的元素内注册一个事件侦听器。
  2. 使用 <slot> 元素用在 light DOM 中声明的元素填充自定义元素。
  3. 在带有 composedPath 的事件上使用 composed: true 来确定您的事件从哪个内部元素冒泡。

以下是我相信您正在寻找的功能示例。如果您点击 Custom Element,它会切换其活动状态(类似于切换下拉菜单)。如果您点击页面上的任何其他元素,自定义元素会自行停用(类似于在失去焦点时隐藏下拉列表)。

// Define the custom element type
class MySpan extends HTMLSpanElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    
    const text = 'Custom Element.';
    const style = document.createElement('style');
    style.textContent = `
      span {
        padding: 5px;
        margin: 5px;
        background-color: gray;
        color: white;
      }
      
      .active {
        background-color: lightgreen;
        color: black;
      }      
    `;
    this.span = document.createElement('span');
    this.span.innerText = text;
    this.span.addEventListener('click',(event) => { 
      console.log('CUSTOM ELEMENT: Clicked inside custom element.'); 
      this.handleClick(event);
    });
    
    this.shadowRoot.append(style,this.span);
  }
  
  handleClick(event) {
    // If the event is from the internal event listener,// the target will be our span element and we can toggle it.
    // If the event is from outside the element,// the target cannot be our span element and we should
    // deactiviate it.
    if (event.target === this.span) {
      this.span.classList.toggle('active');
    }
    else {
      this.span.classList.remove('active');
    }
  }
}
customElements.define('my-span',MySpan,{ extends: 'span' });

// Insert an instance of the custom element
const div1 = document.querySelector('#target');
const mySpan = new MySpan();
div1.appendChild(mySpan);

// Add an event listener to the page
function handleClick(event) {
  // If we didn't click on the custom element,let it
  // know about the event so it can deactivate its span.
  if (event.target !== mySpan) {
    console.log(`PAGE: Clicked on ${ event.target }. Notifying custom element.`);
    mySpan.handleClick(event);
  }
}
document.body.addEventListener('click',(event) => handleClick(event));
p {
  padding: 5px;
  background-color: lightgray;
}
<p id="target">This is a paragraph.</p>
<p>This is a second paragraph.</p>
<p>This is a third paragraph.</p>
<p>This is a fourth paragraph.</p>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?