首页 > 解决方案 > 窗口的角度主机侦听器:滚动触发两次;到底是怎么回事?

问题描述

所以我试图设置表头的位置,以匹配它们在页面最初构建时的位置(水平),以及向下滚动时它们在页面顶部的固定位置栏中的位置。

我的策略是<th>在 ngAfterViewInit 中获取每个的 offsetLeft 属性,保存它们,然后在它们位于固定栏中并从表的上下文中取出时使用它来显式设置每个的左侧位置(定位将否则崩溃)。

该表具有以下结构:

<table>
    <thead [class.header-fixed]="isFixed" id="my-header">
        <tr>
            <th scope="col"><span>column title</span></th>

所以在组件的顶部我有:

private headerItems: number[] = [];
private fixedPosition: number; //set dynamically but can be set explicitly
public isFixed = false;

这是 ngAfterViewInit():

ngAfterViewInit(){
    ...
    let header = document.getElementById('my-header');
    for (var i = 0; i < header.children[0].children.length; i++) {
        let headerItem = <HTMLElement> header.children[0].children[i]; 
        this.headerItems.push(headerItem.offsetLeft);
    }
    ...
}

并捕捉卷轴:

@HostListener("window:scroll", ['$event']) onScroll($event) {

    const documentScrollTop = this.document.documentElement.scrollTop;
    let header = document.getElementById('my-header');
    ...
    if ((documentScrollTop > this.fixedPosition) && (!this.isFixed)) {
        this.isFixed = true;
        for (var i = 0; i < header.children[0].children.length; i++) {
            let headerItem = <HTMLElement> header.children[0].children[i];
            headerItem.style.left = this.headerItems[i].toString();
        }
    } else if ((this.isFixed) && (documentScrollTop < this.fixedPosition)) {
        this.isFixed = false;
    }
    ...
}

虽然这不是特别 Angularish,但我认为这不是问题的原因。这里的目的是一次抓住左边的位置,然后在必要时重复使用它们(有一些响应性影响,但我现在并不担心)。

所以基本上当我运行它时,发生的情况是每滚动一个像素,事件就会触发两次,并且代码会运行两次。这两个事件看起来完全相同,并且具有完全相同的时间戳。这不一定是问题(只是奇怪),但 headerItems 的内容是奇怪的不同。在第一个事件中,所有值都是 0。在第二个事件中,它们是正确的。为什么当它们只设置一次时会发生这种情况?事实上,initialheaderItems是一个没有长度的空数组,所以它永远不应该用 0 填充。当我检查this时,只有一个headerItems数组,所以它不会以某种方式重复。

我尝试仅在数组中的最后一项的值大于 1 时设置左侧定位(因此仅在值正确时设置,但这感觉就像是完全破解),但这不起作用,并且我不知道为什么不。我没有收到任何错误。

这到底是怎么回事?

标签: angulartypescriptscroll

解决方案


推荐阅读