介紹
我今天這個偶然發現,我真的可以看到在很多應用中,這種執行的需要。現在我不能保證這是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