簡體   English   中英

Angular 2路由參數更改,但組件不重新加載

[英]Angular 2 route param changes, but component doesn't reload

所以,基本上我需要在更改url參數的id后重新加載我的組件。 這是我的player.component.ts

import {Component, OnInit, AfterViewInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
declare var jQuery: any;

@Component({
  selector: 'video-player',
  templateUrl: './player.component.html',
  styleUrls: ['./player.component.less']
})

export class VideoPlayerComponent implements OnInit, AfterViewInit {
  playerTop: number;
  currentVideoId: number;

  constructor(
    private _route: ActivatedRoute,
    private _router: Router
  ) {

  }

  ngOnInit(): void {
    this._route.params.subscribe(params => {
      this.currentVideoId = +params['id'];
      console.log( this.currentVideoId );
      this._router.navigate(['/video', this.currentVideoId]);
    });
  }

  ngAfterViewInit(): void {
    if (this.videoPageParams(this.currentVideoId)) {
      console.log( "afterViewInit" );
      let params = this.videoPageParams(this.currentVideoId);
      let fakeVideoItemsCount = Math.floor(params.containerWidth / params.videoItemWidth);
      this.insertFakeVideoItems( this.currentVideoId, fakeVideoItemsCount);
      this.changePlayerPosition( params.videoItemTop );
    }

  }

  videoPageParams( id ): any {
    let videoItemTop = jQuery(`.videoItem[data-id="${id}"]`).position().top;
    let videoItemWidth = jQuery('.videoItem').width();
    let containerWidth = jQuery('.listWrapper').width();
    return {
      videoItemTop,
      videoItemWidth,
      containerWidth
    };
  }

  changePlayerPosition( videoItemTop ): void {
    this.playerTop = videoItemTop;
  }

  insertFakeVideoItems( id, fakeVideoItemsCount ): void {
    let fakeVideoItemHTML = `<div class="videoItem fake"></div>`;
    let html5playerHeight = jQuery('#html5player').height();
    let videoItemIndex = jQuery(`.videoItem[data-id="${id}"]`).index() + 1;
    let videoItemInsertAfterIndex;
    let videoItemRow = Math.ceil(videoItemIndex / fakeVideoItemsCount);
    let videoItemRowBefore = videoItemRow - 1;
    if ( videoItemIndex <= 4 ) {
      videoItemInsertAfterIndex = 0;
    } else {
      videoItemInsertAfterIndex = (videoItemRowBefore * fakeVideoItemsCount);
    }
    let videoItemInsertAfter = jQuery('.videoItem').eq(videoItemInsertAfterIndex);

    for ( let i = 0; i < fakeVideoItemsCount; i++ ) {
      $(fakeVideoItemHTML).insertBefore(videoItemInsertAfter);
    }
    jQuery(`.videoItem.fake`).css('height', html5playerHeight);

  }

}

player.component.html

<video
    class="video"
    preload="auto"
    [attr.data-id]="currentVideoId"
    src="">
</video>

<videos-list></videos-list>

videoList.component.html

<div class="videoItem" *ngFor="let video of videos" [attr.data-id]="video.id">
    <a [routerLink]="['/video', video.id]">
        <img [src]='video.thumbnail' alt="1">
    </a>
</div>

所以,當我點擊<a [routerLink]="['/video', video.id]">videoList.component.html它改變路線/視頻/ 10例如,但部分來自player.component.ts其中操縱DOM不會再次觸發 - DOM操作不會更新

我試圖通過this._router.navigate(['/video', this.currentVideoId]);手動導航到路線this._router.navigate(['/video', this.currentVideoId]); 但不知怎的,它不起作用。

問題有沒有辦法在每次路由參數在同一個URL中更改時運行操作DOM的函數?

DOM不會更新,因為ngOnInit只被觸發一次,因此即使您嘗試從子節點“重新導航”回父節點也不會更新,因為父節點在任何時候都沒有從DOM中刪除。

解決這個問題的一個選擇是,您可以使用Subject ,當路由發生時,讓我們將選擇的視頻ID發送給父級,父級訂閱更改並執行您要求它執行的任何操作,這意味着調用將更新的函數DOM,所以你想要重新執行的是ngOnInitngAfterViewInit

你提到你曾經嘗試過使用過

this._router.navigate(['/video', this.currentVideoId])

讓我們來看看。 可能有一些觸發函數的click事件。 讓我們說它看起來如下,我們只是在劇中添加主題

navigate(id) {
  VideoPlayerComponent.doUpdate.next(id)
  this._router.navigate(['/video', this.currentVideoId])
}

讓我們在您的父級中聲明Subject ,並訂閱更改:

public static doUpdate: Subject<any> = new Subject();

並在構造函數中讓我們訂閱更改...

constructor(...) {
    VideoPlayerComponent.doUpdate.subscribe(res => {
        console.log(res) // you have your id here
        // re-fire whatever functions you need to update the DOM
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM