Javascript 使用Angular 2 router将不同的值传递给同一组件

Javascript 使用Angular 2 router将不同的值传递给同一组件,javascript,angular,typescript,Javascript,Angular,Typescript,以下代码为同一组件AppComponent提供三种不同的路由,包括/、/route2和/route3 import { Component, OnInit, OnChanges } from '@angular/core'; import { NavigationEnd, Router, ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs/Subscription'; import 'rxjs

以下代码为同一组件
AppComponent
提供三种不同的路由,包括
/
/route2
/route3

import { Component, OnInit, OnChanges } from '@angular/core';
import { NavigationEnd, Router, ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';  
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';  

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'This is the title!';
  bodyHTML = 'Here is the content!';
  routerSub:Subscription;

  constructor(private router:Router) { 
      console.log('inside the constructor!');
      console.log(router.url);
   }

  ngOnInit(){       
    // listen to NavigationEnd events
    this.routerSub = this.router.events.filter(e=>e instanceof NavigationEnd)
      // capture the new URL
      .map(e.NavigationEnd => e.url)
      .subscribe(url => {
        /* TODO: use URL to update the view */
      });
  }

  // When the component is destroyed, you must unsubscribe to avoid memory leaks
  ngOnDestroy(){
    this.routerSub.unsubscribe();
  }
}
问题在于
AppComponent
title
bodyHTML
属性在选择不同的路由时不会更改值

需要对下面的代码进行哪些具体更改,以便当用户选择每个不同路线时,应用程序将为
标题
正文HTML
提供不同的值?

以下是几分钟内在任何计算机上重现问题的步骤:


创建种子应用程序:

首先,我在以下步骤中使用Angular CLI创建了一个seed应用程序:

cd C:\projects\angular-cli
ng new routes-share-component
cd C:\projects\angular-cli\routes-share-component
ng serve

仅更改4个文件:

接下来,我只更改了4个文件,如下所示:

我添加了
app.routing.ts
,内容如下:

import { Routes, RouterModule } from '@angular/router';
import { AppComponent } from './app.component';

const appRoutes: Routes = [
    { path: '', component: AppComponent },
    { path: 'route2', component: AppComponent },
    { path: 'route3', component: AppComponent }
];

export const routing = RouterModule.forRoot(appRoutes);
我将
app.component.ts
更改为以下内容:

import { Component, OnInit, OnChanges } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnChanges {
  title = 'This is the title!';
  bodyHTML = 'Here is the content!'

  constructor(private _router:Router, private route:ActivatedRoute) { 
      console.log('inside the constructor!');
      console.log(route.url);
      console.log(_router.url);
 }

 ngOnInit() {
     console.log('inside ngOnInit()');
     let currentUrl = this._router.url; /// this will give you current url
     console.log(currentUrl);
     if(currentUrl=='/'){this.title='Home Page Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route2'){this.title='Route 2 Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route3'){this.title='Route 3 Title';this.bodyHTML='Body goes here.';}
     console.log(this.route.url);
 }
 ngOnChanges() {
     console.log('inside ngOnChanges()!');
     let currentUrl = this._router.url; /// this will give you current url
     console.log(currentUrl);      
     if(currentUrl=='/'){this.title='Home Page Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route2'){this.title='Route 2 Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route3'){this.title='Route 3 Title';this.bodyHTML='Body goes here.';}
     console.log(this.route.url);
 }

}
<div style="text-align:left">
  <h1>{{title}}</h1>
  <p>{{bodyHTML}}</p>
</div>
类似地,
app.component.html
被简化为以下内容:

import { Component, OnInit, OnChanges } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Router } from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnChanges {
  title = 'This is the title!';
  bodyHTML = 'Here is the content!'

  constructor(private _router:Router, private route:ActivatedRoute) { 
      console.log('inside the constructor!');
      console.log(route.url);
      console.log(_router.url);
 }

 ngOnInit() {
     console.log('inside ngOnInit()');
     let currentUrl = this._router.url; /// this will give you current url
     console.log(currentUrl);
     if(currentUrl=='/'){this.title='Home Page Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route2'){this.title='Route 2 Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route3'){this.title='Route 3 Title';this.bodyHTML='Body goes here.';}
     console.log(this.route.url);
 }
 ngOnChanges() {
     console.log('inside ngOnChanges()!');
     let currentUrl = this._router.url; /// this will give you current url
     console.log(currentUrl);      
     if(currentUrl=='/'){this.title='Home Page Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route2'){this.title='Route 2 Title';this.bodyHTML='Body goes here.';}
     if(currentUrl=='/route3'){this.title='Route 3 Title';this.bodyHTML='Body goes here.';}
     console.log(this.route.url);
 }

}
<div style="text-align:left">
  <h1>{{title}}</h1>
  <p>{{bodyHTML}}</p>
</div>
请注意,
ngOnInit()
块在控制台中打印,但
ngOnChanges()
块不打印。这意味着无论选择哪条路线,标题始终为
主页标题

需要对上述代码进行哪些具体更改,以便每条路线在浏览器中为
标题
正文HTML
打印不同的值?


@belletJuice的建议:

根据@甲壳虫果汁的建议,我尝试了以下新版本的
AppComponent
,但它在
RouterSubscription
行和
this.routerSub=this.router.events.filter(…)
行显示了编译错误

import { Component, OnInit, OnChanges } from '@angular/core';
import { NavigationEnd, Router, ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';  
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';  

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'This is the title!';
  bodyHTML = 'Here is the content!';
  routerSub:Subscription;

  constructor(private router:Router) { 
      console.log('inside the constructor!');
      console.log(router.url);
   }

  ngOnInit(){       
    // listen to NavigationEnd events
    this.routerSub = this.router.events.filter(e=>e instanceof NavigationEnd)
      // capture the new URL
      .map(e.NavigationEnd => e.url)
      .subscribe(url => {
        /* TODO: use URL to update the view */
      });
  }

  // When the component is destroyed, you must unsubscribe to avoid memory leaks
  ngOnDestroy(){
    this.routerSub.unsubscribe();
  }
}

还有什么需要改变的吗?

你需要意识到两件事:

  • 当Angular导航到使用相同组件的新路由时,它不会重新初始化该组件。因此,您的
    ngOnInit
    仅在第一次加载组件时运行

  • 当任何组件属性发生更改时,不会触发ngOnChanges。当父组件更改数据绑定属性(如
    @Input()someProp
    所示)时,会触发该属性。因此,您的
    ngOnChanges
    也不会被触发

当路由改变但组件没有改变时,更新模型的一种方法是注入路由器,监听
路由器。可观察到的事件
并对那里的路由改变作出反应

应用程序组件.ts

import {NavigationEnd, Router} from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';
...

routerSub:Subscription;

ngOnInit(){       
  // listen to NavigationEnd events
  this.routerSub = this.router.events.filter(e=>e instanceof NavigationEnd)
    // capture the new URL
    .map((e:NavigationEnd) => e.url)
    .subscribe(url => {
      /* TODO: use URL to update the view */
    });
}

// When the component is destroyed, you must unsubscribe to avoid memory leaks
ngOnDestroy(){
  this.routerSub.unsubscribe();
}

顺便说一句,让多条路由解析到同一个组件可能不是一个好主意。考虑换一个吧! 在OP的哪个类中添加您建议的代码?为什么将多个结果解析为同一内容不是一个好主意?此应用程序的目的是使多个搜索引擎友好的路由使用相同的模板。@CodeMed此代码将在
app.component.ts
中运行。我对搜索引擎优化知之甚少,所以我不能建议如何使一个有角度的应用程序对搜索引擎优化友好。但是,您正在使用多个路由来解决路由参数旨在解决的问题。我不知道拥有
/route1
/route2
/route/1
/route/2
(最后的参数)对搜索引擎优化有什么好处,我只是添加了一份新的
应用组件的副本,并说明了剩余的编译错误。我还需要更改哪些内容?@CodeMed当您请求帮助时,请复制错误消息(如果适用)。您是否从'rxjs/Subscription'导入{Subscription}
?从'rxjs/Subscription
添加
导入{Subscription}消除了第一个编译错误,但是
过滤器(…)
行仍然抛出
[ts]属性'filter',在类型'observeable'上不存在。