如何定位<content>下的Shadow DOM事件?

rha*_*oto 7 web-component shadow-dom polymer

我试图了解源DOM中的哪些事件通过<content>元素在shadow DOM中接收时的样子.我正在阅读Shadow DOM W3C草案,我并不完全理解它,但听起来事件要从EventListener附件的角度"重新定位".

在事件路径跨越多个节点树的情况下,调整事件关于事件目标的信息以维持封装.事件重定向是计算调度事件的节点的每个祖先的相对目标的过程.相对目标是在保持封装的同时最准确地表示给定祖先的调度事件的目标的节点.

在事件发送时:

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

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

<!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>
Run Code Online (Sandbox Code Playgroud)

当我在Chrome 38.0.2075.0金丝雀上运行时,当我点击按钮时,我得到:

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
Run Code Online (Sandbox Code Playgroud)

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

MouseEvent {dataTransfer: null, toElement: div#internal-container, fromElement: null, y: 15, x: 82…} test.html:17
DIV internal-container test.html:20
Run Code Online (Sandbox Code Playgroud)

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

  1. 这是它应该工作的方式,并且
  2. 如果是这样,是否有另一种方法可以将从轻型DOM重新定位的事件重新定位到影子DOM?

如果有人想问,"你想做什么?",除了理解这种行为之外,我不是要做任何其他事情.

ebi*_*del 13

影子dom的事件很棘手.我尝试在下面捕捉一个题库.

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

是的.如果您在Chrome中进行测试,则会获得原生阴影.


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

在您的示例中,您将事件记录在阴影dom内部,因此它仍然可以在那里看到.如果您还在元素外部添加"click"侦听器,则目标看起来好像来自元素:

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

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

'click'事件起泡.这就是你BUTTON在顶级例子中看到的原因.为什么你会看到它?你看到它是因为按钮不是元素阴影dom的一部分.它在光明的dom和元素的目标中.重要的是要记住轻型DOM节点仍然在逻辑上位于主文档中.它们不会移动到阴影dom中,只是在<content>插入点处渲染.


顺便说一下,您的示例中有几个Polymerized修复:

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