【问题标题】:Angular nested component routingAngular 嵌套组件路由
【发布时间】:2018-08-03 11:20:22
【问题描述】:

我有一个导航栏组件,它有一个 routerLink

 <p>
  <a routerLink="/user">User</a>
</p>

以及我正在向其传递值的 UserComponent 下的嵌套组件

@Component({
  selector: 'app-user',
  template: `
    <input #box (keyup.enter)="onEnter(box.value)">
    <div *ngIf="box.size > 0">
      <app-order [value]="value"></app-order>
    </div>`

})
export class UserComponent implements OnInit {

  value = '';

  onEnter(value: string) {
    this.value = value;
  }

  constructor() {
  }

  ngOnInit() {
  }

}

订单组件

@Component({
  selector: 'app-order',
  template:`{{id}}`
})
export class OrderComponent implements OnInit {

  @Input() id:String;

  constructor() { }

  ngOnInit() {
  }

}

现在,当我输入用户链接时,我会看到链接和传递的值。当我再次单击该链接时,我将获得具有价值的相同页面。如何更改此行为,以便当我再次单击路由按钮时,我得到没有传递值的输入?

【问题讨论】:

    标签: angular typescript angular-router


    【解决方案1】:

    我在点击导航栏上的相关按钮时尝试刷新页面时遇到了同样的问题。

    Angular 声明在同一个 URL 上的导航没有任何效果,因为应用程序的状态由它的当前 URL 表示。

    有一个解决方法:onSameUrlNavigation

    不幸的是,这个选项只允许守卫和解析器在导航到相同的 URL 时再次运行,所以如果你激活它,你会发现......什么都没有!

    所以我用这个类创建了自己的解决方法:

    /**
     * Abstract class that allows derived components to get refreshed automatically on route change.
     * The actual use case is : a page gets refreshed by navigating on the same URL and we want the rendered components to refresh
     */
    export abstract class AutoRefreshingComponent implements OnInit, OnDestroy {
      public routerEventsSubscription: Subscription;
      protected router: Router;
    
      constructor() { 
        this.router = AppInjector.get(Router);
      }
    
      /**
       * Initialization behavior. Note that derived classes must not implement OnInit.
       * Use initialize() on derived classes instead.
       */
      ngOnInit() {
        this.initialize();
        this.routerEventsSubscription = this.router.events.filter(x => x instanceof NavigationEnd).subscribe(res => {
          this.initialize();
        });
      }
    
      /**
       * Destruction behavior. Note that derived classes must not implement OnDestroy.
       * Use destroy() on derived classes instead.
       */
      ngOnDestroy(): void {
        this.routerEventsSubscription.unsubscribe();
        this.destroy();
      }
    
      /**
       * Function that allows derived components to define an initialization behavior
       */
      abstract initialize(): void;
    
      /**
       * Function that allows derived components to define a destruction behavior
       */
      abstract destroy(): void;
    
    }
    

    AppInjector 指的是这个:

    import {Injector} from '@angular/core';
    
    /**
     * Allows for retrieving singletons using `AppInjector.get(MyService)` (whereas
     * `ReflectiveInjector.resolveAndCreate(MyService)` would create a new instance
     * of the service).
     */
    export let AppInjector: Injector;
    
    /**
     * Helper to access the exported {@link AppInjector}, needed as ES6 modules export
     * immutable bindings; see http://2ality.com/2015/07/es6-module-exports.html
     */
    export function setAppInjector(injector: Injector) {
        if (AppInjector) {
            // Should not happen
            console.error('Programming error: AppInjector was already set');
        }
        else {
            AppInjector = injector;
        }
    }
    

    在您的 AppModule 中:

    import { setAppInjector } from './app.injector';
    
    // ...
    
    export class AppModule {
      constructor(private injector: Injector) {
        setAppInjector(injector);
      }
    }
    

    然后让所有需要的组件扩展AutoRefreshingComponent

    在你的情况下:

    @Component({
      selector: 'app-user',
      template: `
        <input #box (keyup.enter)="onEnter(box.value)">
        <div *ngIf="box.size > 0">
          <app-order [value]="value"></app-order>
        </div>`
    
    })
    export class UserComponent extends AutoRefreshingComponent {
    
      value = '';
    
      onEnter(value: string) {
        this.value = value;
      }
    
      constructor() {
      }
    
      initialize() {
         // Reset your box value
      }
    
      destroy() {
      }
    
    }
    

    这对于您想要实现的目标可能有点过头了,但每次您想在相同的 URL 导航上刷新组件时它都会很有用。

    如果这有帮助,请告诉我。

    【讨论】:

    • 不幸的是,这不起作用:( OnSameUrlNavigation 解决方法似乎也需要编写很多代码。
    • 我提供了完整的可重用代码,出于您的目的,您只能复制 this.router.events.filter(x =&gt; x instanceof NavigationEnd).subscribe(res =&gt; {/** Your code **/ }); 部分。不要忘记 onSameUrlNavigation: 'reload' 在您的 RouterModule 配置中
    • 我已经添加了 onSameUrlNavigation 参数并且它有效。
    • @bkubiak 很高兴它有帮助!随意接受答案
    猜你喜欢
    • 2015-08-01
    • 1970-01-01
    • 2016-12-19
    • 1970-01-01
    • 2020-12-23
    • 2016-09-14
    • 2016-09-09
    • 2019-01-13
    • 2019-08-04
    相关资源
    最近更新 更多