從?Angular?Route?中提前獲取數(shù)據(jù)的方法詳解
介紹
提前獲取意味著在數(shù)據(jù)呈現(xiàn)在屏幕之前獲取到數(shù)據(jù)。本文中,你將學(xué)到,在路由更改前怎么獲取到數(shù)據(jù)。通過(guò)本文,你將學(xué)會(huì)使用 resolver, 在 Angular App 中應(yīng)用 resolver,應(yīng)用到一個(gè)公共的預(yù)加載導(dǎo)航。
你為什么應(yīng)該使用 Resolver
Resolver 在路由跟組件之間扮演著中間件服務(wù)的角色。假設(shè)你有一個(gè)表單,沒(méi)有數(shù)據(jù)時(shí),你想向用戶一個(gè)空的表單,當(dāng)在加載用戶數(shù)據(jù)時(shí)展示一個(gè) loader,然后當(dāng)數(shù)據(jù)返回時(shí),填充表單并隱藏 loader。
通常,我們都會(huì)在組件的 ngOnInit() 鉤子函數(shù)中獲取數(shù)據(jù)。也就是說(shuō),組件加載完之后,我們發(fā)起數(shù)據(jù)請(qǐng)求。
在 ngOnInit() 中操作,我們需要在每個(gè)需要的組件加載后,在其路由頁(yè)面中添加 loader 展示。Resolver 可以簡(jiǎn)化 loader 的添加使用。你可以只添加一個(gè)適用于每個(gè)路由的 loader,而不是每個(gè)路由中都添加 loader。
本文將結(jié)合示例來(lái)解析 resolver 的知識(shí)點(diǎn)。以便于你可以牢記它并在項(xiàng)目中使用它。
在應(yīng)用中使用 Resolver
為了在應(yīng)用中使用 resolver,你需要準(zhǔn)備一些接口。你可以通過(guò) JSONPlaceholder 來(lái)模擬,而不需要自己開(kāi)發(fā)。
JSONPlaceholder 是一個(gè)很棒的接口資源,你可以借助它更好學(xué)習(xí)前端的相關(guān)概念而不被接口所約束。
現(xiàn)在,接口的問(wèn)題解決了,我們可以開(kāi)始 resolver 的應(yīng)用了。一個(gè) resolver 就是一個(gè)中間件服務(wù),所以我們將創(chuàng)建一個(gè)服務(wù)。
$ ng g s resolvers/demo-resolver --skipTests=true
--skipTests=true 跳過(guò)生成測(cè)試文件
src/app/resolvers 文件夾中創(chuàng)建了一個(gè)服務(wù)。resolver 接口中有一個(gè) resolve() 方法,它有兩個(gè)參數(shù):route(ActivatedRouteSnapshot 的實(shí)例)和 state(RouterStateSnapshot 的實(shí)例)。
loader 通常是在 ngOnInit() 中編寫(xiě)所有的 AJAX 請(qǐng)求,但是邏輯將會(huì)在 resolver 中實(shí)現(xiàn),替代 ngOnInit()。
接著,創(chuàng)建一個(gè)服務(wù)來(lái)獲取 JSONPlaceholder 中列表數(shù)據(jù)。然后在 resolver 中底調(diào)用,接著在路由中配置 resolve信息,(頁(yè)面將會(huì)等待)直到 resolver 被處理。在 resolver 被處理之后,我們可以通過(guò)路由來(lái)獲取數(shù)據(jù)然后展示在組件中。
創(chuàng)建服務(wù)并編寫(xiě)邏輯獲取列表數(shù)據(jù)
$ ng g s services/posts --skipTests=true
現(xiàn)在,我們成功創(chuàng)建了服務(wù),是時(shí)候編寫(xiě)一個(gè) AJAX 請(qǐng)求的邏輯了。
model 的使用能夠幫助我們減少錯(cuò)誤。
$ ng g class models/post --skipTests=true
post.ts
export class Post {
id: number;
title: string;
body: string;
userId: string;
}model 就緒,是時(shí)候獲取帖子 post 的數(shù)據(jù)了。
post.service.ts
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Post } from "../models/post";
@Injectable({
providedIn: "root"
})
export class PostsService {
constructor(private _http: HttpClient) {}
getPostList() {
let URL = "https://jsonplaceholder.typicode.com/posts";
return this._http.get<Post[]>(URL);
}
}現(xiàn)在,這個(gè)服務(wù)隨時(shí)可被調(diào)用。
demo-resolver.service.ts
import { Injectable } from "@angular/core";
import {
Resolve,
ActivatedRouteSnapshot,
RouterStateSnapshot
} from "@angular/router";
import { PostsService } from "../services/posts.service";
@Injectable({
providedIn: "root"
})
export class DemoResolverService implements Resolve<any> {
constructor(private _postsService: PostsService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this._postsService.getPostList();
}
}帖子列表數(shù)據(jù)從 resolver 中返回。現(xiàn)在,你需要一個(gè)路由去配置 resolver,從路由獲取數(shù)據(jù),然后讓數(shù)據(jù)展示在組件中。為了進(jìn)行路由跳轉(zhuǎn),我們需要?jiǎng)?chuàng)建一個(gè)組件。
$ ng g c components/post-list --skipTests=true
為了路由可見(jiàn),在 app.component.ts 添加 router-outlet。
<router-outlet></router-outlet>
現(xiàn)在,你可以配置 app-routing.module.ts 文件了。下面的片段代碼將有助于你理解路由配置 resolver。
app-routing-module.ts
import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { PostListComponent } from "./components/post-list/post-list.component";
import { DemoResolverService } from "./resolvers/demo-resolver.service";
const routes: Routes = [
{
path: "posts",
component: PostListComponent,
resolve: {
posts: DemoResolverService
}
},
{
path: "",
redirectTo: "posts",
pathMatch: "full"
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}一個(gè) resolve 已經(jīng)添加到路由配置中了,它將發(fā)起一個(gè) HTTP 請(qǐng)求,然后當(dāng) HTTP 請(qǐng)求成功返回后,允許組件初始化。路由將組裝獲取到的 HTTP 請(qǐng)求返回的數(shù)據(jù)。
怎么應(yīng)用一個(gè)預(yù)加載導(dǎo)航
向用戶展示一個(gè)請(qǐng)求正在進(jìn)行,我們?cè)?AppComponent 中編寫(xiě)一個(gè)公共且簡(jiǎn)單的 loader。你可以根據(jù)需要自定義。
app.component.html
<div class="loader" *ngIf="isLoader"> <div>Loading...</div> </div> <router-outlet></router-outlet>
app.component.ts
import { Component } from "@angular/core";
import {
Router,
RouterEvent,
NavigationStart,
NavigationEnd
} from "@angular/router";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent {
isLoader: boolean;
constructor(private _router: Router) {}
ngOnInit() {
this.routerEvents();
}
routerEvents() {
this._router.events.subscribe((event: RouterEvent) => {
switch (true) {
case event instanceof NavigationStart: {
this.isLoader = true;
break;
}
case event instanceof NavigationEnd: {
this.isLoader = false;
break;
}
}
});
}
}當(dāng)導(dǎo)航開(kāi)始,isLoader 值被賦予 true,頁(yè)面中,你將看到下面的效果。

當(dāng) resolver 處理完之后,它將會(huì)被隱藏。
現(xiàn)在,是時(shí)候從路由中獲取值并將其展示出來(lái)。
port-list.component.ts
import { Component, OnInit } from "@angular/core";
import { Router, ActivatedRoute } from "@angular/router";
import { Post } from "src/app/models/post";
@Component({
selector: "app-post-list",
templateUrl: "./post-list.component.html",
styleUrls: ["./post-list.component.scss"]
})
export class PostListComponent implements OnInit {
posts: Post[];
constructor(private _route: ActivatedRoute) {
this.posts = [];
}
ngOnInit() {
this.posts = this._route.snapshot.data["posts"];
}
}如上所示,post 的值來(lái)自 ActivatedRoute 的快照信息 data。這值都可以獲取,只要你在路由中配置了相同的信息。
我們?cè)?HTML 進(jìn)行如下渲染。
<div class="post-list grid-container">
<div class="card" *ngFor="let post of posts">
<div class="title"><b>{{post?.title}}</b></div>
<div class="body">{{post.body}}</div>
</div>
</div>CSS 片段樣式讓其看起來(lái)更美觀。
port-list.component.css
.grid-container {
display: grid;
grid-template-columns: calc(100% / 3) calc(100% / 3) calc(100% / 3);
}
.card {
margin: 10px;
box-shadow: black 0 0 2px 0px;
padding: 10px;
}推薦使用 scss 預(yù)處理器編寫(xiě)樣式
從路由中獲取數(shù)據(jù)之后,它會(huì)被展示在 HTML 中。效果如下快照。

至此,你已經(jīng)了解完怎么應(yīng)用 resolver 在你的項(xiàng)目中了。
總結(jié)
結(jié)合用戶體驗(yàn)設(shè)計(jì),在 resolver 的加持下,你可以提升你應(yīng)用的表現(xiàn)。了解更多,你可以戳官網(wǎng)。
本文是譯文,采用的是意譯的方式,其中加上個(gè)人的理解和注釋,原文地址是:www.pluralsight.com/guides/pref…
到此這篇關(guān)于從 Angular Route 中提前獲取數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Angular Route獲取數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
AngularJs Understanding Angular Templates
本文主要介紹AngularJs Understanding Angular Templates的資料,這里整理了詳細(xì)的資料及簡(jiǎn)單示例代碼,有興趣的小伙伴的參考下2016-09-09
Angular4學(xué)習(xí)教程之HTML屬性綁定的方法
這篇文章主要給大家介紹了關(guān)于Angular4學(xué)習(xí)教程之HTML屬性綁定的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
Angular實(shí)現(xiàn)form自動(dòng)布局
這篇文章主要介紹了Angular實(shí)現(xiàn)form自動(dòng)布局的相關(guān)資料,以代碼片段的形式分析了Angular實(shí)現(xiàn)form自動(dòng)布局的實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下2016-01-01
使用Angular9和TypeScript開(kāi)發(fā)RPG游戲的方法
這篇文章主要介紹了使用Angular9和TypeScript開(kāi)發(fā)RPG游戲的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
AngularJS數(shù)據(jù)源的多種獲取方式匯總
在AngularJS中獲取數(shù)據(jù)源的方式有很多種,本文給大家整理幾種獲取數(shù)據(jù)源的方式,對(duì)angularjs獲取數(shù)據(jù)源的方式相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧2016-02-02
angularJs使用ng-repeat遍歷后選中某一個(gè)的方法
今天小編就為大家分享一篇angularJs使用ng-repeat遍歷后選中某一個(gè)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
AngularJS中的Directive自定義一個(gè)表格
本篇文章給大家介紹在angularjs中自定義一個(gè)有關(guān)表格的directive,涉及到angularjs directive相關(guān)知識(shí),對(duì)本文感興趣的朋友一起學(xué)習(xí)吧2016-01-01
AngularJS實(shí)現(xiàn)的生成隨機(jī)數(shù)與猜數(shù)字大小功能示例
這篇文章主要介紹了AngularJS實(shí)現(xiàn)的生成隨機(jī)數(shù)與猜數(shù)字大小功能,結(jié)合完整實(shí)例形式分析了AngularJS隨機(jī)數(shù)生成與數(shù)值判定相關(guān)操作技巧,需要的朋友可以參考下2017-12-12

