Подтвердить что ты не робот

Отслеживание положения прокрутки и уведомление об этом других компонентах

Есть ли простой способ отслеживать положение прокрутки браузера и уведомлять об этом больше, чем один компонент.

Случай использования: в прокрутке я хочу иметь возможность изменять классы различных элементов на странице, основываясь на том, где я. В предыдущей версии angular это было несколько возможно через плагин afix (тот же для jQuery). Разумеется, есть возможность написать незавершенную JS, инициализировать его при запуске приложения и испустить событие. Звучит грязно, и эмиссия событий довольно дорога для этого типа вещей.

Каковы мои варианты здесь?


ОБНОВЛЕНИЕ (после предложений):

Итак, вот что я пробовал:

Я создал компонент:

import {Component} from "angular2/core";

@Component({
    selector: '[track-scroll]',
    host: {'(window:scroll)': 'track($event)'},
    template: ''
})

export class TrackScrollComponent {
    track($event) {
        console.debug("Scroll Event", $event);
    }
}

добавлен атрибут главной директивы приложения:

<priz-app track-scroll>

И добавил компонент как один из поставщиков в верхнем компоненте:

import {TrackScrollComponent} from "../../shared/components/track-scroll.component";

@Component({
  selector: 'priz-app',
  moduleId: module.id,
  templateUrl: './app.component.html',
  directives: [ROUTER_DIRECTIVES, SecureRouterOutlet, AppHeader, TrackScrollComponent],
  providers: [AuthenticationService]
})

Все еще ничего...

Другое обновление:

Перемещено track-scroll в один из элементов div основного шаблона:

<div class="container-fluid" track-scroll>
    <div class="row">
        <div class="col-md-12">
            <app-header></app-header>
            <secure-outlet signin="Login" unauthorized="AccessDenied"></secure-outlet>
        </div>
    </div>
</div>

И теперь приложение загружается с полностью пустым экраном. FUN FUN FUN...

ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ (это сработало для меня).

  • Определить дефект:
import {Directive} from "angular2/core";

@Directive({
    selector: '[track-scroll]',
    host: {'(window:scroll)': 'track($event)'}
})

export class TrackScrollDirective {
    track($event: Event) {
        console.debug("Scroll Event", $event);
    }
}
  1. Добавьте его как директиву в любое место, где оно используется:
directives: [TrackScrollDirective]
  1. Добавить атрибут в любой элемент, где мы хотим отслеживать событие:
<div class="col-md-12" track-scroll>
4b9b3361

Ответ 1

Я думаю, что самый простой способ - это любой заинтересованный компонент, который прослушивает событие прокрутки.

  @Component({
    ...
    // alternative to `@HostListener(...)`
    // host: {'(window:scroll)': 'doSomething($event)'}
  })
  class SomeComponent {
    @HostListener('window:scroll', ['$event']) 
    doSomething(event) {
      // console.debug("Scroll Event", document.body.scrollTop);
      // see András Szepesházi comment below
      console.debug("Scroll Event", window.pageYOffset );
    }
  }

plunker

Plunker с помощью @HostListener()

Подсказка:

bootstrap(MyComponent, [
    provide(PLATFORM_DIRECTIVES, {useValue: [TrackScrollDirective], multi:true})]);

делает директиву универсально, не добавляя ее в список всех компонентов directive: [...].

Ответ 2

Я был вынужден решить это по-другому, потому что мне нужно было посмотреть несколько прокручиваемых элементов в окне. Я создал директиву для просмотра положения прокрутки элемента:

@Directive({
  selector: '[scroll]'
})
export class ScrollDir {
  @Output() setScroll = new EventEmitter();
  private scroll: number;

  constructor(private el: ElementRef) { }

  @HostListener('scroll', ['$event'])
  scrollIt() { this.scroll = event.srcElement.scrollTop }

  reset() {  this.el.nativeElement.scrollTop = this.scroll }
}

Затем на любом компоненте, содержащем элемент прокрутки, который нуждался в этом элементе, я мог бы @ViewChild директивой следующим образом:

@Component({
  selector: 'parent',
  template: `
    <div class="container" scroll>
      // *ngFor=""...
    </div>
  `
})
export class ParentComp implements AfterViewChecked {

  @ViewChild(ScrollDir) scroll: ScrollDir;

  ngAfterViewChecked() {
    this.scroll.reset()
  }
}