gpt4 book ai didi

angular - 在 cdk-virtual-scroller 中获取静态组件引用? (引用文献被回收)

转载 作者:行者123 更新时间:2023-12-03 16:03:53 25 4
gpt4 key购买 nike

我们最近将可滚动列表转换为 CDK Virtual Scroller。 (带有 angular/cdk 7.3.7 的 Angular 7.2.12)

总之,似乎VirtualScrollViewport正在回收组件实例,而不仅仅是文档建议的模板。

Live MCVE on StackBlitz (更新以反射(reflect)编辑 1)。

编辑 1

一位同事提醒我,我们现在使用命名引用而不是 ViewChildren() ,像这样:
HelloComponent (在 *cdkVirtualFor 内):

@Component({
selector: 'hello',
template: `<h1 [class.active]="active">Data Item {{item}} !</h1>`,
styles: [`.active {background-color: red; color: white}`]
})
export class HelloComponent {
@Input() item: any;
active: boolean = false;
toggle = () => this.active = !this.active;
}

并在应用程序中实现它,例如:
<cdk-virtual-scroll-viewport itemSize="75">
<ng-container *cdkVirtualFor="let item of data" templateCacheSize=0>
<hello #hi [item]="item" (click)="clickByReference(hi)"></hello>
</ng-container>
</cdk-virtual-scroll-viewport>

// Non-essentials hidden, see StackBlitz
export class AppComponent {
data = Array.from(Array(100).keys())
clickByReference = (element: any): void => element.toggle();
}

它会将被点击元素的背景颜色更改为红色,但是在滚动时,其他元素(大概是那些与某些缓存索引匹配的元素?)将已经是红色的!激活其中之一也将清除原件。

The source suggests那个 templateCacheSize可能有帮助,但没有。

原装

可滚动区域包含我们使用 @ViewChildren() 引用的组件。和 QueryList并且我们使用 *ngFor 中的索引来跟踪我们正在执行的操作(现在 *cdkVirtualFor ),像这样:
<cdk-virtual-scroll-viewport itemSize="75">
<ng-container *cdkVirtualFor="let item of data; let i = index">
<hello #hi
[item]="item"
(click)="click(i)"></hello>
</ng-container>
</cdk-virtual-scroll-viewport>

然后,从页面中,我们与列表中的组件进行通信:
export class AppComponent  {
@ViewChildren('hi') hiRefs: QueryList<HelloComponent>;
data = Array.from(Array(100).keys())

click = (i: number) => this.hiRefs["_results"][i].say(`Hello as ${i}`);
}

当然,现在模板渲染在虚拟滚动容器中,只有第一个 n被渲染到 DOM 中。因此,如果您向下滚动列表超出最初加载的内容, hiRefs不包含对具有相应索引的项目的引用,抛出 ReferenceError对于提供的 ["_results"][i] .

我尝试了 trackBy但没有取得任何成果。

编辑 : 一个同事也试图传递一个命名引用,奇怪的是也有同样的问题。

更新 HelloComponent
@Component({
selector: 'hello',
template: `<h1 [class.active]="active">Data Item {{item}} !</h1>`,
styles: [`.active {background-color: red}`]
})
export class HelloComponent {
@Input() item: any;
active: boolean;

say = (something: any) => this.active = !this.active;
}

并在应用程序中实现它,例如:
<hello #hi [item]="item" (click)="clickByReference(hi)"></hello>

它会将被点击元素的背景颜色更改为红色,但是在滚动时,其他元素(大概是那些匹配相同索引的元素)已经是红色的,尽管没有使用 @ViewChildren() QueryList根本!

CDK 似乎正在回收组件实例引用?

我使用方法 clickByReference() 更新了 StackBlitz ,并将上面的重命名为 clickByIndex() .

如何正确获取对列表中组件的引用以调用其上的方法?

最佳答案

默认情况下,CdkVirtualForOf caches 20 ViewRef s到不再呈现到 DOM 中的组件以提高滚动性能。

虽然这些更新显示新的界限 @Input() s,它们不会更新它们的内部状态,因此之前缓存的副本会被重新使用。

似乎唯一的解决方案是设置 templateCacheSize: 0 :

<ng-container *cdkVirtualFor="let item of data; templateCacheSize: 0">

这样,一旦组件不再可见,组件就会被销毁,状态也会丢失。

进一步阅读 https://github.com/angular/material2/issues/15838和一个 doc PR .

关于angular - 在 cdk-virtual-scroller 中获取静态组件引用? (引用文献被回收),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55696084/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com