介绍
我今天这个偶然发现,我真的可以看到在很多应用中,这种执行的需要。现在我不能保证这是100%最好的技术,但是我尽量让这种方法尽可能地具有灵活性。
我提出的方法有两个阶段。第一阶段和第二阶段将增加总数为years * months + years * months * days
,因此在1年内您将有12 + 365
事件。
舞台范围
第一阶段:当一个月下来点击进入实际的一天代表事件,被点击,而无需在当天的事件。
阶段2:将选定的日期传播回月份。
只是在深入研究之前,该应用程序由被嵌套在下面的顺序3个组成部分:app => month => day
这是所有需要的HTML。应用程序。组件托管几个月,month.component托管几天,day.component不做任何事情,而是以文本形式显示它的一天。
app.component.html
<app-month *ngFor="let month of months" [data-month]="month"></app-month>
month.component.html
<app-day *ngFor="let day of days" [data-day]="day">{{day}}</app-day>
day.component.html
<ng-content></ng-content>
这是相当股票标准的东西。
第1阶段
让我们看看month.component.ts
,我们想从我们的委托事件。
// obtain a reference to the month(this) element
constructor(private element: ElementRef) { }
// when this component is clicked...
@HostListener('click', ['$event'])
public onMonthClick(event) {
// check to see whether the target element was a child or if it was in-fact this element
if (event.target != this.element.nativeElement) {
// if it was a child, then delegate our event to it.
// this is a little bit of javascript trickery where we are going to dispatch a custom event named 'delegateclick' on the target.
event.target.dispatchEvent(new CustomEvent('delegateEvent'));
}
}
在这两个阶段1和2,有只有 1级的警告,并且是;如果你嵌套了您的day.component.html
内子元素,你要么需要实现冒泡为此,更好的逻辑,如果陈述,或快速黑客会。在day.component.css
:host *{pointer-events: none;}
现在,我们需要告诉我们day.component预计我们的
delegateEvent
事件。因此,在
day.component.ts
所有你需要做的(在大多数的角度可能的方式)是...
@HostListener('delegateEvent', ['$event'])
public onEvent() {
console.log("i've been clicked via a delegate!");
}
这工作,因为打字稿不关心该事件是否是天然的或没有,它只是绑定新javascript事件添加到元素,因此我们可以通过event.target.dispatchEvent
“本地”调用它,就像我们在month.component.ts
中做的那样。
第1阶段即将结束,我们现在已成功地将我们的月份活动委托给我们的日子。
第2阶段
如果说要在我们的授权事件中day.component
运行逻辑的一点点,然后将其返回到month.component
所以会发生什么 - 这样它就可以用随身携带它自己的功能在一个非常面向对象的方法?幸运的是,我们可以非常轻松地实现这一点!
在month.component.ts
更新到以下。所有改变的是我们现在要通过我们的事件调用来传递一个函数,并且我们定义了回调函数。
@HostListener('click', ['$event'])
public onMonthClick(event) {
if (event.target != this.element.nativeElement) {
event.target.dispatchEvent(new CustomEvent('delegateEvent', { detail: this.eventDelegateCallback}));
}
}
public eventDelegateCallback(data) {
console.log(data);
}
剩下的就是在day.component.ts
内调用此函数...
public onEvent(event) {
// run whatever logic you like,
//return whatever data you like to month.component
event.detail(this.day);
}
不幸的是我们的回调函数有点含糊这里命名,但是打字稿会抱怨,如果命名,否则不被定义的对象字面CustomEventInit
财产。
多事件漏斗
这个方法的其他很酷的事情是,你不应该定义不止这个数的事件更多,因为你可以通过这个代表团渠道中的所有事件,然后运行逻辑内day.component.ts
通过event.type
过滤...
month.component.ts
@HostListener('click', ['$event'])
@HostListener('mouseover', ['$event'])
@HostListener('mouseout', ['$event'])
public onMonthEvent(event) {
if (event.target != this.element.nativeElement) {
event.target.dispatchEvent(new CustomEvent('delegateEvent', { detail: this.eventDelegateCallback }));
}
}
个
day.component.ts
private eventDelegateCallback: any;
@HostListener('delegateEvent', ['$event'])
public onEvent(event) {
this.eventDelegateCallback = event.detail;
if(event.type == "click"){
// run click stuff
this.eventDelegateCallback(this.day)
}
}
有独立的模块,其处理此。我发现“dom-delegate”工作得很好。就我所知,在ng2中没有内置任何东西。 – Chrillewoodz
如果这是一个问题......这将是一个角度优化问题。您不必担心汇总事件以进行优化。 –
几个月前我遇到了类似的问题,据我所知,您所描述的方法是以原始角度执行此操作的最佳方法。使用较少的事件侦听器检查点击目标。我建议的唯一的事情就是把逻辑放在一个服务或指令中(指令可能会更好,因为你需要每个月div),这样代码是干净的并且与组件分离。毕竟,它是html逻辑,而不是组件逻辑 – FussinHussin