天天看點

angular6+ 環境下 監控路由變化來設定title

1. 首先探讨下如何設定title

1. 顯而易見的方法是把元件的屬性綁定到 HTML 的 

<title>

 标簽上,像這樣:

<title>{{This_Does_Not_Work}}</title>
           

但是這樣不行的,應用程式的根元件(<app></app>)是一個包含在 

<body>

 标簽裡的元素,該 HTML 的 

<title>

 在文檔的 

<head>

 元素裡,在 

<body>(

<app>

之外,Angular 的資料綁定無法通路到它。

2.  我們可以這樣 document.title = 'my-title'。但是這樣做不夠優雅,并且document隻是浏覽器的元素,這樣如果程式需要泡在其他環境下,那麼就需要更改代碼了。

3. 好在,Angular 在浏覽器平台的包中,提供了一個Title服務,彌補了這種差異。Title服務是一個簡單的類,提供了一個API,用來擷取和設定目前HTML文檔的标題。

  • getTitle(): string

     —— 擷取目前 HTML 文檔的标題。
  • setTitle( newTitle: string)

     —— 設定目前 HTML 文檔的标題。
export class AppComponent {
  public constructor(private titleService: Title ) { }

  public setTitle( newTitle: string) {
    this.titleService.setTitle( newTitle );
  }
}
           

4. 這樣以後就算程式不運作在浏覽器環境中,隻要替換Title這個依賴注入的服務就可以了,不需要更改業務代碼。

2. 那麼angular服務如何監控路由變化來動态設定title呢

如果每一個子產品都寫一遍setTitle是不是很累,那麼該如何使用呢。

在 app.component.ts 中

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, NavigationEnd, Router} from '@angular/router';
import {Title} from '@angular/platform-browser';
import {filter, map} from 'rxjs/operators';

@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
    constructor(private router: Router,
                private title: Title) {
    }


    setTitle() {
        this.router.events
            .pipe(
                filter(event => event instanceof NavigationEnd),
                map(() => this.router)
            )
            .subscribe((event) => {

                // 更改頁面title
                const titles = this.getTitle(this.router.routerState, this.router.routerState.root);
                const title = titles[titles.length - 1];
                if (title) {
                    this.title.setTitle(title);
                }
            });
    }

    getTitle(state, parent) {
        const data = [];
        if (parent && parent.snapshot.data && parent.snapshot.data.title) {
            data.push(parent.snapshot.data.title);
        }

        if (state && parent) {
            data.push(...this.getTitle(state, state.firstChild(parent)));
        }
        return data;
    }


    ngOnInit() {
        this.setTitle();
    }
}
           

在 app-routing.module.ts 中

import {NgModule} from '@angular/core';
import {PreloadAllModules, RouterModule, Routes} from '@angular/router';

// path: '**' 要放在最底下
const routes: Routes = [
    {path: '', loadChildren: './tabs/tabs.module#TabsPageModule', data: {title: '導航'}},
    {path: 'home', loadChildren: './home/home.module#HomePageModule', data: {title: '首頁'}},
    {path: '**', loadChildren: './page-not-found/page-not-found.module#PageNotFoundPageModule', data: {title: '頁面未找到'}},


];

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