【问题标题】:How are Shadow DOM events from under <content> targeted?<content> 下的 Shadow DOM 事件如何定位?
【发布时间】:2014-06-29 22:22:41
【问题描述】:

我试图了解当通过 &lt;content&gt; 元素在影子 DOM 中接收到源自 light DOM 的事件时,这些事件是什么样子的。我正在阅读Shadow DOM W3C Draft,我并不完全理解它,但从 EventListener 附件的角度来看,这听起来像是要“重新定位”事件。

在事件路径跨越多个节点树的情况下, event关于事件目标的信息按顺序调整 保持封装。事件重定向是一个计算过程 事件所在节点的每个祖先的相对目标 派出。相对目标是最准确的节点 表示给定祖先的已调度事件的目标,而 维护封装。

事件派发时:

  • Event target 和 currentTarget 属性必须返回相对的 调用事件侦听器的节​​点的目标

所以这里有一个简单的 Polymer 自定义元素,它只是将其子元素放入容器中,并向容器(在影子 DOM 中)添加一个 click EventListener。在这种情况下,孩子是一个按钮。

<!DOCTYPE html>
<html>
  <head>
    <script src="bower_components/platform/platform.js"></script>
    <link rel="import" href="bower_components/polymer/polymer.html">
  </head>
  <body unresolved>
    <polymer-element name="foo-bar">
      <template>
        <div id="internal-container" style="background-color:red; width:100%;">
          <content></content>
        </div>
      </template>
      <script>
       Polymer("foo-bar", {
         clickHandler: function(event) {
           console.log(event);
           var element = event.target;
           while (element) {
             console.log(element.tagName, element.id);
             element = element.parentElement;
           }
         },

         ready: function() {
           this.shadowRoot.querySelector('#internal-container').addEventListener('click', this.clickHandler);
         }
       });
      </script>
    </polymer-element>

    <foo-bar id="custom-element">
      <button>Click me</button>
    </foo-bar>
  </body>
</html>

当我在 Chrome 38.0.2075.0 canary 上运行它时,当我点击按钮时,我得到:

MouseEvent {dataTransfer: null, toElement: button, fromElement: null, y: 19, x: 53…}altKey: falsebubbles: truebutton: 0cancelBubble: falsecancelable: truecharCode: 0clientX: 53clientY: 19clipboardData: undefinedctrlKey: falsecurrentTarget: nulldataTransfer: nulldefaultPrevented: falsedetail: 1eventPhase: 0fromElement: nullkeyCode: 0layerX: 53layerY: 19metaKey: falsemovementX: 0movementY: 0offsetX: 45offsetY: 10pageX: 53pageY: 19path: NodeList[0]relatedTarget: nullreturnValue: truescreenX: 472screenY: 113shiftKey: falsesrcElement: buttontarget: buttontimeStamp: 1404078533176toElement: buttontype: "click"view: WindowwebkitMovementX: 0webkitMovementY: 0which: 1x: 53y: 19__proto__: MouseEvent test.html:17
BUTTON  test.html:20
FOO-BAR custom-element test.html:20
BODY  test.html:20
HTML  test.html:20

当我点击容器时,我得到:

MouseEvent {dataTransfer: null, toElement: div#internal-container, fromElement: null, y: 15, x: 82…} test.html:17
DIV internal-container test.html:20

所以我在 light 或 shadow DOM 中获得了一个事件目标,具体取决于 source 元素所在的 DOM。在这两种情况下,我都希望从 shadow DOM 中获得一个目标,因为那是附加 EventListener 的位置。我的问题是:

  1. 这是它应该的工作方式吗,并且
  2. 如果是这样,是否有其他方法可以让从 light DOM 重新定位到 shadow DOM 的事件冒泡?

如果有人想问,“你想做什么?”,除了理解行为之外,我不会做任何具体的事情。

【问题讨论】:

    标签: polymer web-component shadow-dom


    【解决方案1】:

    shadow dom 的事件很棘手。我尝试在下面捕获一个大脑转储。

    1. 这是应该的工作方式吗

    是的。如果你在 Chrome 中测试,你会得到原生 shadow dom。


    我在HTML5Rocks - Shadow DOM 301 文章中写了一个关于事件重定向的部分。基本上,重定向意味着源自 shadow dom 的事件看起来像是来自元素本身。

    在您的示例中,您将事件记录在 shadow dom 内部,因此仍然可以看到它。如果您还在元素之外添加了一个“点击”侦听器,那么目标看起来就好像它来自该元素:

    <script>
      var el = document.querySelector('#custom-element');
      el.addEventListener('click', function(e) {
        console.log(e.target.tagName); // logs FOO-Bar
      });
    </script>
    

    http://jsbin.com/womususe/1/edit

    “点击”事件冒泡。这就是为什么您在顶级示例中看到 BUTTON 的原因。为什么你会看到它?您看到它是因为该按钮不是您元素的 shadow dom 的一部分。它在 light dom 和元素的目标中。重要的是要记住轻 DOM 节点在逻辑上仍然在主文档中。它们没有移动到 shadow dom 中,只是在 &lt;content&gt; 插入点处渲染。


    顺便说一句,您的示例有几个聚合修复:

    1. this.shadowRoot.querySelector('#internalcontainer') -> this.$.internalcontainerthis.$.ID 是 Polymer 的“自动节点查找”功能。
    2. 您根本不需要使用addEventListener()。相反,请使用&lt;div id="internalcontainer" on-click="{{clickHandler}}"&gt;。这是一个声明性事件处理程序。

    【讨论】:

    • 感谢您的回复(以及您在世界上发布的所有其他信息)!我知道该按钮不是影子 DOM 的一部分;这就是为什么我很惊讶在影子 DOM 侦听器上看到它。规范说,“事件目标和 currentTarget 属性必须返回调用事件侦听器的节​​点的相对目标。”所以我希望事件在通过&lt;content&gt; 元素时被重新定位。只是为了多余地清楚,您是说它符合影子 DOM 侦听器的规范,以从其主机的 DOM 以及它自己的 DOM 接收事件目标?
    • 是的,这很正常。事件重定向是 other 方向:防止外部 DOM 看到 ShadowDOM 内部的节点。
    • @ScottMiles 假设影子 DOM 中级别为 -10 的元素触发了“响应”事件。通过重定向,它将在上面的所有 10 个级别(主机)上传播。同时,级别 -5 的元素也会触发一个名为“response”的事件,并且此事件也会发生重定向。如果在级别 -4 上,您想为级别 -5 上的“响应”事件附加一个处理程序(不知道在级别 -10 上触发的事件),它也会不情愿地处理来自 -10 的事件。在中型或大型应用程序中,您不可能知道所有来自深“水下”的事件。你对此有何看法?谢谢。
    猜你喜欢
    • 2021-07-27
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 2018-09-15
    • 2014-09-08
    相关资源
    最近更新 更多