Polymer在兄弟元素之间发送/接收事件

4
假设我有两个兄弟元素,<element-b> 触发一个事件。如何让 <element-a> 在不必向父级添加命令式代码的情况下监听该事件?
<dom-module id="parent-element">
  <element-a></element-a>
  <element-b></element-b>
</dom-module>

其中<element-a><element-b>是:

<dom-module id="element-a">
  <template>
    <style include="shared-styles">
    </style>
  </template>

  <script>
    Polymer({
      is: 'element-a',
      listeners: {
        'element-b': 'handleEvent',
      },
      ready: function() {
        console.log('fired from element a')
        this.fire('element-a', {employee: ''});
      },
      handleEvent: function (e) {
        console.log('received element b event', e)
      }
    });
  </script>
</dom-module>

<dom-module id="element-b">
  <template>
    <style include="shared-styles">
    </style>
  </template>

  <script>
    Polymer({
      is: 'element-b',
      listeners: {
        'element-a': 'handleEvent',
      },
      ready: function() {
        console.log('fired from element b')
        this.fire('element-b', {employee: ''});

      },
      handleEvent: function (e) {
        console.log('received element a event', e)
      }
    });
  </script>

谢谢!

1个回答

4
你可以使用 <iron-signals> 来实现。
在一个元素中添加 <iron-signals> 监听器:
// element-b
<iron-signals on-iron-signal-element-a="_onSignalElementA"></iron-signals>

_onSignalElementA: function(e) {
  const newDate = e.detail;
  ...
}

...并在另一个中触发一个带有数据的iron-signal事件:

// element-a
this.fire('iron-signal', {name: 'element-a', data: new Date()});

HTMLImports.whenReady(() => {
  Polymer({
    is: 'x-foo'
  });
  Polymer({
    is: 'element-a',
    _onClick: function() {
      this.fire('iron-signal', {name: 'element-a', data: new Date()});
    }
  });
  
  Polymer({
    is: 'element-b',
    _onSignalElementA: function(e) {
      this._message = `b received: ${e.detail}`;
    }
  });
});
<head>
  <base href="https://polygit.org/polymer+1.11.0/components/">
  <script src="webcomponentsjs/webcomponents-lite.js"></script>
  <link rel="import" href="polymer/polymer.html">
  <link rel="import" href="iron-signals/iron-signals.html">
</head>
<body>
  <x-foo></x-foo>

  <dom-module id="x-foo">
    <template>
      <element-a></element-a>
      <element-b></element-b>
    </template>
  </dom-module>
  <dom-module id="element-a">
    <template>
      <button on-tap="_onClick">Fire event</button>
    </template>
  </dom-module>
  <dom-module id="element-b">
    <template>
      <iron-signals on-iron-signal-element-a="_onSignalElementA"></iron-signals>
      <div>[[_message]]</div>
    </template>
  </dom-module>
  
</body>

codepen


谢谢。我最终使用了它,但您知道为什么建议避免使用它吗?“注意:尽可能使用控制器(父元素)来协调通信,而不是使用iron-signals。” - user3240644
我认为这是一个设计决策。一方面,中介者模式通过额外的管道(和潜在的冗长代码)限制了数据范围。另一方面,使用<iron-signals>可以减少代码大小,但代价是可维护性下降。在更复杂的示例中,如果element-aelement-b不是直接兄弟关系而是远房亲戚,<iron-signals>仍然可以工作,但可能更难理解您的代码。 - tony19
那么另一种选择是将父级作为中介者,这会导致冗长的代码。有没有办法使代码更清晰,并封装中介者的行为,而不是直接将代码添加到父级中? - user3240644

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接