[英]StencilJS IonContent scroll event firing to child component
IonContent 有自己的滾動事件,我需要在子組件中監聽它。
我正在監聽沒有觸發的窗口滾動事件,我意識到它被包裹在處理自己滾動事件的 IonContent 元素中。
我的布局示例如下
<ion-content scrollEvents={ true } onIonScroll={ this.windowScrolled.bind(this) }>
<bf-filter-selections scrollElement={this.ionContent} ref={(e) => this.filterElementWrapper = e}></bf-filter-selections>
</ion-content>
我嘗試了幾件事:
這可能會回到我缺乏的一些基本 js 知識上,但這令人沮喪,因為當內容滾動時,我似乎無法在我的子組件中觸發事件。
在我嘗試過的事情中,這就是它們不起作用的原因
1)從父組件調用子組件的方法,代碼告訴我它在子組件上找不到“windowScroll”。
filterElementWrapper 是 HTMLElement
filterElementWrapper: any;
windowScrolled(e: any) {
this.filterElementWrapper.windowScroll();
}
子組件方法
@Listen('onscroll')
@Watch('scrollOffset')
public windowScroll() {
console.log('scroll');
if (window.pageYOffset > this.resultHeaderElementOffset) {
this.resultHeaderElement.classList.add("sticky");
} else {
this.resultHeaderElement.classList.remove("sticky");
}
}
2) 嘗試將父組件的引用傳遞給子組件
我不再有支持此功能的代碼,但基本上在子組件中,我創建了一個“any”類型的屬性並將父級的引用傳遞給子級。
然后我創建了一個“Listen('ionScroll', { target: this.scrollElement})”。
該方法永遠不會在孩子中被觸發。
3) 在子組件上創建一個名為“scrollOffset”的屬性。 我在觸發滾動時更新了此屬性,並“觀察”子組件中的屬性更改。 同樣,該方法不會觸發。
設置滾動偏移屬性的主要包裝器
<ion-content scrollEvents={ true } onIonScroll={ this.windowScrolled.bind(this) }>
<bf-filter-selections scroll-offset={this.scrollTop} scrollElement={this.ionContent} ref={(e) => this.filterElementWrapper = e}></bf-filter-selections>
</ion-content>
在父級中設置的狀態屬性
@State() scrollTop: number = 0;
在滾動時更新狀態屬性
windowScrolled(e: any) {
this.scrollTop = e.detail.currentY;
}
已被監視的子屬性
@Prop() scrollOffset: number;
觀察屬性變化的方法
@Listen('onscroll')
@Watch('scrollOffset')
public windowScroll() {
console.log('scroll');
if (window.pageYOffset > this.resultHeaderElementOffset) {
this.resultHeaderElement.classList.add("sticky");
} else {
this.resultHeaderElement.classList.remove("sticky");
}
}
在所有情況下,都不會調用該方法。
我不是 100% 確定為什么您的方法 3 已經開始工作,但我認為這是因為onIonScroll
處理程序更新了scrollOffset
狀態,然后觸發了@Watch()
裝飾方法。
你在這里混淆了一些東西,所以我會先試着澄清一下:如果一個元素發出一個事件<EventName>
,那么你可以通過添加一個on<EventName>
屬性來綁定一個監聽器到那個元素到它,例如:
<my-button onclick={console.log} />
將函數console.log
綁定到click
事件。 在 JavaScript 中做同樣的事情的等價物是:
document.querySelector('my-button').addEventListener('click', console.log);
如果你做了addEventListener('onclick')
,那將不起作用,因為事件名稱是click
而不是onclick
。 如果要將事件處理程序添加到 HTML 中的元素,則僅添加on
前綴(請參閱DOM onevent handlers )。 或者,這也適用於 JavaScript:
document.querySelector('my-button').onclick = console.log;
(不同之處在於您只能設置一個onclick
屬性,但如果您使用addEventListener
則可以附加多個click
事件偵聽器)
請注意,大小寫在 JavaScript 中很重要,但在 HTML 中不重要,所以
<my-button onClick={console.log} />
相當於第一個例子。
理想情況下,我想在子組件中收聽父組件的滾動事件,但仍然無法正常工作。
這是不可能的,因為事件只能向上冒泡 DOM 樹而不能向下冒泡。 這個概念是“事件上升,道具下降”。 對於您的情況,我能想到的最干凈的解決方案與您已經嘗試過的類似:偵聽父級中的事件,然后將必要的信息作為道具傳遞給子級:
import { h, Component, State } from '@stencil/core';
import { ScrollDetail } from '@ionic/core';
@Component({ tag: 'my-parent' })
export class Parent {
@State() scrollTop = 0;
setScrollTop = (e: CustomEvent<ScrollDetail>) => {
this.scrollTop = e.detail.scrollTop;
}
render() {
return (
<ion-content scrollEvents onIonScroll={this.setScrollTop}>
<child-component scrollTop={this.scrollTop} />
</ion-content>
);
}
}
除了使用onIonScroll
作為<ion-content>
的屬性之外,您還可以像這樣使用@Listen()
裝飾器:
@Listen('ionScroll')
setScrollTop(e: CustomEvent<ScrollDetail>) {
this.scrollTop = e.detail.scrollTop;
}
此處您的錯誤是使用'onscroll'
作為事件名稱。
我看到您還嘗試將滾動元素的引用傳遞給孩子。 ion-content
元素不是實際滾動的元素,因此它提供了一個方法getScrollElement
,如果您想執行“本機”操作,例如訪問底層scroll
事件或手動訪問該元素的scrollTop
(我假設是您試圖從您的孩子那里做的事情)。
customElements.whenDefined('ion-content').then(() => {
document.querySelector('ion-content').getScrollElement().then(el => {
el.addEventListener('scroll', () => console.log(el.scrollTop));
});
});
出於某種原因,方法 3 已經開始工作。
我不確定是否是因為我在發布更新后對項目進行了干凈的構建,但現在正在調用該方法並且一切都按預期工作。
不過有一件事,我仍然想知道這是否是最好的方法? 理想情況下,我想在子組件中收聽父組件的滾動事件,但仍然無法正常工作。
如果有人有更清潔的解決方案,請告訴我
我個人會選擇第一個,因為它最接近中斷/推送。 因此,如果狀態發生變化,子組件會立即獲得狀態變化的信息。
你真的很接近,但你只需要將@Method裝飾器添加到你的子函數中。 這個裝飾器使函數公開可用,你可以從父級調用它。 從我的角度來看,這是實現這一點的最簡單和最好的方法。
這里只是你的第二個和第三個解決方案的旁注:這兩個概念開始工作是因為 stencil監視屬性並在應用更改時重新渲染組件。 在某些情況下,這不是必需的 - 這會產生不必要的開銷。 此外,我認為手表實際上是作為投票設計的,但我不確定這一點。
此外,您無法獲得父事件,因為事件的行為就像 - 它從根開始並“向下”穿過樹,直到到達交互元素。 這稱為捕獲階段。 一旦它到達元素,它就會冒泡。 所以理論上事件會下降,你可以捕獲它們,但前提是元素在層次結構中高於交互。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.