Polymer 1.0:如何在不使用 <iron-signals> 的情况下将事件传递给 child-node 元素?

Polymer 1.0: How to pass an event to a child-node element without using <iron-signals>?

建议使用 <iron-signals> 将事件沿 DOM 树传播到自定义元素。

下面,我问一个不同的问题。

问题

How do I:

  • pass an event down to a direct child node (custom element)
  • from a parent (custom element)
  • without using <iron-signals>?

代码

这就是我目前所拥有的。但是没用。

parent-element.html
<dom-module id="parenet-element">   
  <template is="dom-bind">
    <child-element></child-element>
    <paper-button on-tap="_handleTap"></paper-button>
  </template>
</dom-module>
<script>
  (function(){
    Polymer({
      is: 'parenet-element',
      _handleTap: function() {
        this.fire("my-event");
      }
    });
  })();
</script>
child-element.html
<dom-module id="child-element"> 
...
</dom-module>
<script>
  (function(){
    Polymer({
      is: 'child-element',
      listeners: {
        "my-event": "foo"
      },
      foo: function(){
        // Do stuff
      }
    });
  })();
</script>
Polymer Slack 网站上的@arthur 说:

Events tend to go up the DOM tree. Going down, you can use a data binding or invoke a method.

Polymer Slack Site

你绝对可以。没有 iron-signals 你有三个选项(我目前知道的):

  1. 获取 parent 并让 child 将事件侦听器附加到 parent
  2. parent 可以让 child 触发相同的事件
  3. 您提到事件只会上升。然后,您可以让 child 元素监听 document 触发该事件(但我认为这很糟糕)

这是一个例子

<!doctype html>
<html>

<head>
  <base href="http://polygit.org/components/">
  <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
  <link href="polymer/polymer.html" rel="import">
</head>

<body>
  <dom-module id="parent-element">
    <template>
      <child-element></child-element>
      <button id="btn" on-tap="_fireParentEvent1">Fire 1!</button>
      <button id="btn" on-tap="_fireParentEvent2">Fire 2!</button>
      <button id="btn" on-tap="_fireParentEvent3">Fire 3!</button>
    </template>
  </dom-module>
  <dom-module id="child-element">
    <template>
      <style>
        :host {
          display: block;
        }
      </style>
      <span id="changeMe">Message</span>
    </template>
  </dom-module>

  <parent-element></parent-element>
  <script>
    (function registerElements() {
      Polymer({
        is: 'parent-element',
        listeners: {
          'event-two': '_attachToChild'
        },
        _attachToChild: function(e) {
          // the parent makes the child fire an event
          var childElement = Polymer.dom(this.root).querySelector('child-element');
          childElement.fire('event-two', e.detail);
        },
        _fireParentEvent1: function(e) {
          // the parent fires an event
          this.fire('event-one', {
            message: 'hello'
          });
        },
        _fireParentEvent2: function(e) {
          this.fire('event-two', {
            message: 'goodbye'
          });
        },
        _fireParentEvent3: function(e) {
          // the parent fires an event
          this.fire('event-three', {
            message: 'game over'
          });
        }
      });

      Polymer({
        is: 'child-element',
        listeners: {
          'event-two': '_handleEventTwo'
        },
        ready: function() {
          var parent = this.parentNode;

          // the child listens to the parent's event
          parent.addEventListener('event-one', function(e) {
            this.$.changeMe.innerHTML = e.detail.message;
          }.bind(this));

          // listen to the document level event (since events travel up)
          // but this option is difficult to control
          document.addEventListener('event-three', function(e) {
            this.$.changeMe.innerHTML = e.detail.message;
          }.bind(this));
        },
        _handleEventTwo: function(e) {
          this.$.changeMe.innerHTML = e.detail.message;
        }
      });
    })();
  </script>
</body>

</html>

使用 Polymer 1.2.4 记录 here 我们可以使用 fire 方法选项并强制子节点(同时仍在父元素内)触发(当然首先监听)一个事件:

this.fire('test', {
    user: {
        name: 'Marios',
        gender: 'male'
    }
}, {
    node: Polymer.dom(this.root).querySelectorAll('my-child-element'),
    bubbles: false
});

我们从一个元素触发了一个自定义事件,但发射器是 my-child-element,所以我们可以在 listeners 对象中附加一个侦听器。我们还防止事件冒泡,因此该事件不会沿着父元素路径向上移动。典型的听众可能是:

Polymer({
    is: 'my-child-element',

    properties: {
        ...
    },
    listeners: {
        'test': '_myHandler'
    },
    _myHandler: function(e) {
        var user = e.detail.user;
        ...
    }
});