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

通过 Shadow DOM 传递带有 composition=false 的标准 JavaScript 事件

如何解决通过 Shadow DOM 传递带有 composition=false 的标准 JavaScript 事件

我有一个自定义的 lit web 组件,它的 Shadow DOM 中包含一个 <input> 元素。我想对自定义元素外部的输入触发的 change 事件做出反应,但 change 事件认具有 composed: false,因此该事件不会通过 Shadow DOM 边界.我可以在组件实现中捕获事件,但 composed 属性是只读的,因此我无法更新它并分派相同的事件对象。我可以使用 new Event('change',{'composed': true}) 创建一个新对象,但是它没有原始事件的 target 之类的属性。什么是好的方法?我应该手动将原始事件的属性复制到新的事件对象吗?

解决方法

不可能多次调度单个 Event 实例,因此即使您可以修改原始事件的 composed 属性,您也无法重新调度它。

因此,您需要创建一个新事件以从您的自定义元素调度,但是您希望如何创建事件以及它应该包含什么的详细信息可能取决于您的用例。我建议尽量保持简单,并制作一个包含您需要的信息的事件,然后发送它。

原生 change 事件不是 composed 可能是有原因的,但是您可以通过创建一个名为 change 的事件并分派它来模拟将其传播出您的自定义元素从您的自定义元素。在大多数情况下,您甚至可能不需要使用 composed,因为只需从您的自定义元素 (this) 分派它就可以在父作用域(从您的影子根上一层)中使用它大多数情况下可能应该处理事件的位置。

您的 shadow root 中有 <input> 的事实可能应该被视为一个实现细节(至少在某些情况下)而不是不必要地暴露在外面,但是当您确实需要直接公开它时,您可以使它可用,例如作为您的自定义元素的属性(然后可以从您的自定义事件访问),或者您可以在事件对象中包含对它的引用(例如,在 CustomEventdetail 属性或自定义事件类)。

例如 here's<vaadint-text-field> 这样的 Vaadin 组件如何传播 change 事件:

const changeEvent = new CustomEvent('change',{
  detail: {
    sourceEvent: e
  },bubbles: e.bubbles,cancelable: e.cancelable
});
this.dispatchEvent(changeEvent);

此处原始事件显式公开为 event.detail.sourceEvent,因此您可以例如从自定义 change 事件(如 event.detail.sourceEvent.target.value)中获取输入值。

如果您通过属性(例如 myInput)公开输入元素,则不需要使用 CustomEventdetail,因为您可以执行类似 event.target.myInput.value 的操作,或者,如果原始 change 事件实际上导致自定义元素上的 value 属性发生更改,您可以改为阅读该事件。

// Dispatch event (in your custom element)
const changeEvent = new Event('change',{
  bubbles: e.bubbles,cancelable: e.cancelable
});
this.dispatchEvent(changeEvent);

// Read the input value in event handler (assuming your custom element
// has declared `myInput` as a reference to the `<input>`)
event.target.myInput.value
// Alternatively access via shadowRoot (not very nice)
event.target.shadowRoot.querySelector('input').value

如果您创建这样的自定义事件类,您还可以在事件中包含自定义属性或方法:

// Declare event class once somewhere
class MyChangeEvent extends Event {
  constructor(sourceEvent) {
    super('change',{
      bubbles: sourceEvent.bubbles,cancelable: sourceEvent.cancelable,});
    this.sourceEvent = sourceEvent;
  }
}

// Trigger a custom event
this.dispatchEvent(new MyChangeEvent(e));

// Access custom event property in an event handler
event.sourceEvent

您当然可以使用您自己的自定义事件名称,例如 change,而不是使用事件名称 my-change-event,但是当您希望自定义元素的行为时,使用 change 应该没问题像原生 <input>,它可能允许您的组件在某些情况下(可能有限制)用作原生 <input> 的替代品,或者如果您只想模仿原生 {{1}开发人员已经熟悉的事件。在大多数情况下,您调度的 change 事件是否创建为 changeEvent 或其他从 CustomEvent 扩展的实例可能无关紧要。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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”。这是什么意思?