Прокрутка на основе фрагмента URL (Angular + NGRX + ElementRef) - PullRequest
2 голосов
/ 07 апреля 2020

У меня есть главная страница с парой разделов. Доступ к каждому разделу можно получить, введя его название фрагмента в URL (например, www.website.com/#introduction - откроет домашнюю страницу и автоматически перейдет к разделу введения). Для этого мне нужно получить контейнерный элемент секции и запустить на нем функцию .scrollIntoView ().

Что я сделал:

  1. Элемент списка, который я создал, store (ngrx), в котором хранятся ElementRef (s) разделов.
  2. В каждом компоненте раздела (расположенном в HomeComponent - родительском элементе разделов) я помещаю @ViewChild(), указывающий на элемент. @ViewChild(‘container’, { static: true }) private container: ElementRef;
  3. Затем в ngAfterViewInit() этого компонента секции я помещаю Store.dispatch(), в котором хранится мой ElementRef.
this.store.dispatch(new HomeActions.SetElementRef({
  linkName: COMP_LINK_NAME,
  elementRef: this.container
}));

Затем в HomeComponent Слушаю разделы Магазин риф this.store.select('sectionRefs'). Отфильтровал его, если его undefined (так как по умолчанию инструкция store = default пуста).

this.sectionRefs$ = this.store.select('sectionRefs').pipe(
    map((data: { sectionRefs: SectionReference[] }) => data.sectionRefs), // transform to a more convenient object
    tap((sectionRefs: SectionReference[]) => this.sectionRefs = sectionRefs), // Updates the sectionRefs array regardless the completion of it (filter below)
    filter((sectionRefs: SectionReference[]) => { // No emission until sectionRefs Element Refs are completed
      return sectionRefs.find((sectionRef: SectionReference) => {
        return (
          sectionRef.element === undefined ||
          sectionRef.element === null ||
          sectionRef.element.nativeElement.offsetHeight === 0 && sectionRef.element.nativeElement.offsetWidth === 0
        );
      }) === undefined // Means that no incompleted sectionRef was found
    }),
    distinctUntilChanged(
      (prev: SectionReference[], next: SectionReference[]) => JSON.stringify(prev) === JSON.stringify(next)
    ),
    first()
);
HomeCompoent: И в конце концов я прослушал фрагмент ActivatedRoute.fra, чтобы проверить, какой ElementRef релевантен для прокрутки. HomeComponent: Активируйте .scrollIntoView () на соответствующем ElementRef.

Проблема в том, что я делаю это, когда страница загружена, поэтому ElementRef.nativeElement.scrollIntoView() прокручивается в неправильное место. Я проверил, чтобы увидеть полученное offsetHeight (ElementRef.nativeElement.offsetHeight), и оно также было неверным. Таким образом, в каждом разделе компонента я обернул действие Store.dispatch() с setTimeout()

setTimeout(() => {
  this.store.dispatch(new HomeActions.SetElementRef({
  linkName: COMP_LINK_NAME,
  elementRef: this.container
  }));
}, 150);

И это работает! Но это похоже на очень плохую практику, чтобы делать эту работу вокруг.

Есть ли другое решение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...