routerlink更改时不调用Angular 2 ngOnInit

Posted

技术标签:

【中文标题】routerlink更改时不调用Angular 2 ngOnInit【英文标题】:Angular 2 ngOnInit is not called when routerlink changes 【发布时间】:2018-02-02 12:36:09 【问题描述】:

我有一个菜单栏,其中包含从 express api 加载的菜单列表,并且每个菜单都引用到具有别名的页面,该别名将是该页面的 URL 当我点击菜单时,我试图加载页面,它已经完成但只有当我刷新页面时 这是我的菜单代码

export class MenuList implements OnInit 

menus:Menu[];
menu:Menu;
page:Page;

constructor(private router:Router,
            private menuService:MenuService) 


getMenus():void 
    this.menuService.getMenus()
        .subscribe(
            menus => this.menus = menus, //Bind to view
            err => 
                // Log errors if any
                console.log(err);
            
        );


getPage(id):void 
    this.menuService.getPage(id)
        .subscribe(
            page => this.page = page, //Bind to view
            err => 
                // Log errors if any
                console.log(err);
            );


ngOnInit():void 
    this.getMenus();

这是我的模板菜单

<div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="navbar"  style="background-color: #97455f">
        <div class="navv">
            <ul *ngFor="let menu of menus">
                <li class="col-lg-1 col-md-1 col-xs-12 col-sm-12"><a [routerLink]="[menu.page.alias]">menu.title</a></li>


            </ul>
        </div>
    </div>

</div><!-- /.navbar-collapse -->

我认为问题出在我的页面组件的 ngOnInit 中,它没有被调用

    @Component(
    selector: 'page',
    templateUrl: './page.component.html'
)
export class PageComponent implements OnInit 
    alias: string;
    page:Page;

    constructor(private router:Router,
                private route: ActivatedRoute,
                private pageService:PageService) 

        this.route.params.subscribe(
            (params : Params) => 
                this.alias = params["alias"];
                console.log(this.alias)
            
        );
    




    ngOnInit():void 
        debugger;
        this.pageService.getPage(this.alias).subscribe(page => 
            this.page = page;
            console.log(this.page);
        );
    


这是我的页面模板

    <p *ngIf="page" [innerHTML]="page.content" ></p>

这是我的应用路由代码

const routes: Routes = [
     path: '', redirectTo: '/home', pathMatch: 'full' ,
     path: ':alias', component: PageComponent ,
     path: 'archived',  component: ArchivedComponent ,
     path: 'home',  component: HomeComponent ,
     path: 'menu',  component: MenuList ,
     path: 'detail/:id', component: ActualiteDetailComponent ,
     path: 'contact',  component: ContactComponent ,

];

@NgModule(
    imports: [ RouterModule.forRoot(routes) ],
    exports: [ RouterModule ]
)
export class AppRoutingModule 

这是我的应用组件

@Component(
  selector: 'my-app',
  template: `
    <menu-list></menu-list>
    <hr>
`

)
export class AppComponent 


Home of application with the menu bar

【问题讨论】:

顺便说一句。路线顺序很重要。您的应用程序中没有任何路由通过PageComponent ?甚至是主页、菜单或联系人。我的意思是更具体的路线应该在顶部,下面更广泛。 我无法从您的问题中得出截断的代码/html 属于哪个组件,也无法得出 menu.page.alias 可能返回的路由名称。 Sharikov Vladislav,是的,所有菜单 url 都从别名传递给 PageComponent,我的问题是当我单击菜单列表时页面内容未加载,但当我刷新页面时,它已加载 【参考方案1】:

当只有一个路由参数发生变化但路由的基础保持不变时,Angular 会重用该组件。 ngOnInit() 只在组件实例化后被调用一次,而在路由改变时不会被调用。

您可以注入路由器并订阅它的事件或参数以获取有关路由更改的通知。

【讨论】:

是的,但如何?我应该用其他东西代替 ngOnInit 吗?例如解析器? 可以注入route:ActivatedRoute订阅route.subscribe(...) Ups,我忘记了`route.**params**.subscribe。无论如何,黛博拉展示了完整的代码。我认为她的回答至少赢得了至少一票;-) 很高兴听到你无论如何都能让它发挥作用。 谢谢,但这很奇怪,大多数时候在每个页面上都有加载数据的 api 调用,如果我使用 angular 不会调用 ngOnInit 的用例是什么routerLink @SunilGarg 但它没有重新渲染(真的没有这样的事情)。 ngOnInit 是组件生命周期,onActivate 是路由器生命周期。它们没有连接。我明白你希望他们是。路由器是独立的模块,组件生命周期甚至不知道它的存在。这会导致尴尬的依赖关系。【参考方案2】:

下面是 Gunter 所说的代码示例:

  constructor(private route: ActivatedRoute)  

  ngOnInit() 
     this.route.params.subscribe(
     params => 
        let id= +params['id'];
        this.getProduct(id);
     );
  

此代码监视参数的更改并执行箭头函数内的任何代码。

【讨论】:

来自您提供的链接:subscribe will only take one argument: either the next handler (a function) or an observer object. 我只传递了一个参数,所以上面的语法应该还是可以的。 这是唯一的解决方案吗? routerLink 和 router.navigate 都不调用ngOnInit 在我的情况下,我只需要调用 ngOnint 没有参数的东西【参考方案3】:

感谢@Günter Zöchbauer 和@DeborahK,它已修复 我从这里更改了页面组件代码

@Component(
selector: 'page',
templateUrl: './page.component.html'
    )
    export class PageComponent implements OnInit 
        alias: string;
        page:Page;

        constructor(private router:Router,
                    private route: ActivatedRoute,
                    private pageService:PageService) 

            this.route.params.subscribe(
                (params : Params) => 
                    this.alias = params["alias"];
                    console.log(this.alias)
                
            );
        

    ngOnInit():void 
            debugger;
            this.pageService.getPage(this.alias).subscribe(page => 
                this.page = page;
                console.log(this.page);
            );
        
    

到这个

@Component(
selector: 'page',
templateUrl: './page.component.html'
    )
    export class PageComponent implements OnInit 
        alias:string;
        page:Page;

        constructor(private router:Router,
                    private route:ActivatedRoute,
                    private pageService:PageService) 

            this.route.params.subscribe(
                (params:Params) => 
                    this.alias = params["alias"];
                    this.pageService.getPage(this.alias).subscribe(page => 
                        this.page = page;
                        console.log(this.page);
                    );
                    console.log(this.alias)
                
            );
        
         ngOnInit():void 
            this.pageService.getPage(this.alias).subscribe(page => 
                this.page = page;
                console.log(this.page);
            );
        
    

【讨论】:

很高兴它对您有用。考虑将代码从构造函数移动到 ngOnInit。获取数据的代码不应该在构造函数中。另外,您无需在 ngOnIt 中重复 getPage 方法调用。 哦!是的。我忘了删除它。谢谢【参考方案4】:
import  Router  from '@angular/router';
...
export class SettingViewComponent implements OnInit 

 constructor(
   private router: Router
 )  

 public ngOnInit(): void 
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;

【讨论】:

以上是关于routerlink更改时不调用Angular 2 ngOnInit的主要内容,如果未能解决你的问题,请参考以下文章

通过单击事件处理程序防止 routerLink 更改路由

Angular2 - 将 routerLink 参数添加到所选表值

canActivate 在订阅更改时不响应 Angular 2 路由器 AngularFire2

canActivate 在订阅更改时不响应 Angular 2 路由器 AngularFire2

无法绑定到“routerlink”,因为它不是使用 angular2-webpack-starter 的已知本机属性 [重复]

Angular中的routerLink 跳转页面和默认路由