在angular2

时间:2017-05-05 19:53:36

标签: javascript angular

我有一个带有事件的组件,如下所示:

<menu-elem (onClick)="reallyCoolEvent($event)"></custom-component>

现在,我可以使用reallyCoolEvent中的EventEmitter触发我的custom-component

@Output() onClick= new EventEmitter();
this.onClick.emit(stuff);

像这样,在我的其他组件中,将调用函数reallyCoolEvent,并将stuff传递给该函数。这非常有效!

现在,让我们说,我想出于任何原因复制该组件,我想从原始事件中触发相同的事件。现在,我正在浏览我的onClick列表,如果它们符合我的标准,我会将它们存储在我在页面上其他位置显示的列表中。当我从那里触发onClick时,事件永远不会被触发。

<menu>
  <menu-elem label="Action 1" (onClick)="superCoolEvent($event)"></menu-elem>
  <menu-elem label="Action 2" (onClick)="superCoolEvent2($event)"></menu-elem>
  <menu-elem label="Action 3" (onClick)="superCoolEvent3($event)"></menu-elem>
</menu>

menu

模板:

<div>
   <ng-content></ng-content>
</div>
<sub-menu *ngFor="let subMenu of subMenus" [style.top]="subMenu.top" [style.left]="subMenu.left" [items]="subMenu.items"></sub-menu>

sub-menu

模板:

<menu-elem *ngFor="let item of items" [label]="item.label"></menu-elem>

通过这样做,我希望能够触发onClick中的<div class="here">并仍然从原始模板触发事件:reallyCoolEvent($event)。我不知道我是否可以这样做。当然onClick未设置,因为我不再拥有模板中的数据。或者至少,我不知道如何获取数据。

我到目前为止唯一的解决方案是复制我的条目:

<menu>
  <menu-elem label="1" (onClick)="superCoolEvent($event)"></menu-elem>
  <menu-elem label="2" (onClick)="superCoolEvent2($event)"></menu-elem>
  <menu-elem label="3" (onClick)="superCoolEvent3($event)"></menu-elem>
  <div class="test">
    <menu-elem label="1" (onClick)="superCoolEvent($event)"></menu-elem>
    <menu-elem label="2" (onClick)="superCoolEvent2($event)"></menu-elem>
    <menu-elem label="3" (onClick)="superCoolEvent3($event)"></menu-elem>
  </div>
</menu>

根据我的标准,我可以显示或不显示,但我不喜欢这种方式,因为模板变得太大而没有。

2 个答案:

答案 0 :(得分:1)

您的基本问题是自定义事件不会在Angular中冒泡。

由于您的menu看起来像这样:

<div>
   <ng-content></ng-content>
</div>
<sub-menu *ngFor="let subMenu of subMenus" [items]="subMenu.items"></sub-menu>

上述模板中sub-menu内触发的任何事件都不会在sub-menu之外自动提供。

因此,如果您希望customEvent模板中的sub-menusub-menu之外可用,则必须手动传播该事件。类似的东西:

<div>
   <ng-content></ng-content>
</div>
<div class="here">
  <sub-menu *ngFor="let item of items" label="item.label" (submenuCustomEvent)="menuCustomEvent.emit($event)"></sub-menu>
</div>

其中submenuCustomEventEventEmitter的{​​{1}}属性,而sub-menu属性为menuCustomEvent的{​​{1}}。

修改

这意味着您的EventEmitter必须看起来像:

menu

,您的sub-menu变为:

@Component({
  .....
  template: `   
    <menu-elem *ngFor="let item of items" 
         [label]="item.label"
         (customEvent)="submenuCustomEvent.emit($event)
    >
    </menu-elem>
   `
})
export class Submenu {
    .....
   @Output()
   submenuCustomEvent = new EventEmitter();
    ....
}

因此,您现在使用menu的模板如下所示:

@Component({
  .....
  template: `   
    <div>
      <ng-content></ng-content>
    </div>
    <sub-menu *ngFor="let subMenu of subMenus" 
       [items]="subMenu.items"
       (submenuCustomEvent)="menuCustomEvent.emit($event)"
    >
    </sub-menu>
   `
})
export class Menu {
    .....
   @Output()
   menuCustomEvent = new EventEmitter();
    ....
}  

注意事项:

  • 如果您需要区分menu嵌套在<menu (menuCustomEvent)="superCoolEvent($event)"> <menu-elem label="Action 1" (customEvent)="superCoolEvent($event)"></menu-elem> <menu-elem label="Action 2" (customEvent)="superCoolEvent2($event)"></menu-elem> <menu-elem label="Action 3" (customEvent)="superCoolEvent3($event)"></menu-elem> </menu> 内的menu-elem事件,您可能需要在sub-menu发出的事件中添加一些其他信息。

  • 我在示例中为submenuCustomEventmenu命名了事件发射器以突出显示差异,但您可以在代码中使用相同的事件发射器名称(即调用所有嵌套事件发射器sub-menu

  • 在此方案中,服务可能有助于避免通过组件层次结构手动连接事件发射器。如果点击onClick内的menu而没有中间事件传播

    ,则可以使用服务直接通知您使用menu-elem的顶级组件/ LI>
  • 最后,您使用的是自定义sub-menu事件。但是,如果直接使用浏览器onClick事件,则可以避免手动传播,因为浏览器click事件会传播。但是,您无法控制所发出事件的形状,因此存在此限制。

答案 1 :(得分:0)

我不确定我是否完全了解你。但是,您可以将子组件的引用注入子组件并使用父组件的偶数组。

 constructor(private myParent: Parent) {}

 go() {
    this.myParent.custometEvent.emit(data);
 }