从 Angular Route 中提前获取数据的方法详解

 更新时间:2022年07月13日 11:05:15   作者:Jimmy  
这篇文章主要介绍了从 Angular Route 中提前获取数据,通过本文,你将学会使用 resolver, 在 Angular App 中应用 resolver,应用到一个公共的预加载导航,本文给大家介绍的非常详细,需要的朋友可以参考下

介绍

提前获取意味着在数据呈现在屏幕之前获取到数据。本文中,你将学到,在路由更改前怎么获取到数据。通过本文,你将学会使用 resolver, 在 Angular App 中应用 resolver,应用到一个公共的预加载导航。

你为什么应该使用 Resolver

Resolver 在路由跟组件之间扮演着中间件服务的角色。假设你有一个表单,没有数据时,你想向用户一个空的表单,当在加载用户数据时展示一个 loader,然后当数据返回时,填充表单并隐藏 loader。

通常,我们都会在组件的 ngOnInit() 钩子函数中获取数据。也就是说,组件加载完之后,我们发起数据请求。

在 ngOnInit() 中操作,我们需要在每个需要的组件加载后,在其路由页面中添加 loader 展示。Resolver 可以简化 loader 的添加使用。你可以只添加一个适用于每个路由的 loader,而不是每个路由中都添加 loader。

本文将结合示例来解析 resolver 的知识点。以便于你可以牢记它并在项目中使用它。

在应用中使用 Resolver

为了在应用中使用 resolver,你需要准备一些接口。你可以通过 JSONPlaceholder 来模拟,而不需要自己开发。

JSONPlaceholder 是一个很棒的接口资源,你可以借助它更好学习前端的相关概念而不被接口所约束。

现在,接口的问题解决了,我们可以开始 resolver 的应用了。一个 resolver 就是一个中间件服务,所以我们将创建一个服务。

$ ng g s resolvers/demo-resolver --skipTests=true

--skipTests=true 跳过生成测试文件

src/app/resolvers 文件夹中创建了一个服务。resolver 接口中有一个 resolve() 方法,它有两个参数:route(ActivatedRouteSnapshot 的实例)和 state(RouterStateSnapshot 的实例)。

loader 通常是在 ngOnInit() 中编写所有的 AJAX 请求,但是逻辑将会在 resolver 中实现,替代 ngOnInit()。

接着,创建一个服务来获取 JSONPlaceholder 中列表数据。然后在 resolver 中底调用,接着在路由中配置 resolve信息,(页面将会等待)直到 resolver 被处理。在 resolver 被处理之后,我们可以通过路由来获取数据然后展示在组件中。

创建服务并编写逻辑获取列表数据

$ ng g s services/posts --skipTests=true

现在,我们成功创建了服务,是时候编写一个 AJAX 请求的逻辑了。

model 的使用能够帮助我们减少错误。

$ ng g class models/post --skipTests=true

post.ts

export class Post {
  id: number;
  title: string;
  body: string;
  userId: string;
}

model 就绪,是时候获取帖子 post 的数据了。

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);
  }
}

现在,这个服务随时可被调用。

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();
  }
}

帖子列表数据从 resolver 中返回。现在,你需要一个路由去配置 resolver,从路由获取数据,然后让数据展示在组件中。为了进行路由跳转,我们需要创建一个组件。

$ ng g c components/post-list --skipTests=true

为了路由可见,在 app.component.ts 添加 router-outlet。

<router-outlet></router-outlet>

现在,你可以配置 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 {}

一个 resolve 已经添加到路由配置中了,它将发起一个 HTTP 请求,然后当 HTTP 请求成功返回后,允许组件初始化。路由将组装获取到的 HTTP 请求返回的数据。

怎么应用一个预加载导航

向用户展示一个请求正在进行,我们在 AppComponent 中编写一个公共且简单的 loader。你可以根据需要自定义。

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;
        }
      }
    });
  }
}

当导航开始,isLoader 值被赋予 true,页面中,你将看到下面的效果。

当 resolver 处理完之后,它将会被隐藏。

现在,是时候从路由中获取值并将其展示出来。

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 的值来自 ActivatedRoute 的快照信息 data。这值都可以获取,只要你在路由中配置了相同的信息。

我们在 HTML 进行如下渲染。

<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 片段样式让其看起来更美观。

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 预处理器编写样式

从路由中获取数据之后,它会被展示在 HTML 中。效果如下快照。

至此,你已经了解完怎么应用 resolver 在你的项目中了。

总结

结合用户体验设计,在 resolver 的加持下,你可以提升你应用的表现。了解更多,你可以戳官网。

本文是译文,采用的是意译的方式,其中加上个人的理解和注释,原文地址是:www.pluralsight.com/guides/pref…

到此这篇关于从 Angular Route 中提前获取数据的文章就介绍到这了,更多相关Angular Route获取数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • angular6.0开发教程之如何安装angular6.0框架

    angular6.0开发教程之如何安装angular6.0框架

    这篇文章主要介绍了angular6.0开发教程之如何安装angular6.0框架,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 详解angularjs 关于ui-router分层使用

    详解angularjs 关于ui-router分层使用

    本篇文章主要介绍了详解angularjs 关于ui-router分层使用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Angular.JS去掉访问路径URL中的#号详解

    Angular.JS去掉访问路径URL中的#号详解

    最近天天都在用AngularJS,各类文档也都看过好几遍,但总是些编程上的事找不到优雅的解决办法。今天终于把AngularJS的项目访问路径URL里的#号去掉了,这个问题不见得有多难,关键是花多长时间去理解AngularJS框架本身,下面来看看详细介绍,需要的朋友可以参考下。
    2017-03-03
  • AngularJS实现给动态生成的元素绑定事件的方法

    AngularJS实现给动态生成的元素绑定事件的方法

    这篇文章主要介绍了AngularJS实现给动态生成的元素绑定事件的方法,结合实例形式分析了AngularJS动态生成元素与事件绑定相关操作技巧,需要的朋友可以参考下
    2016-12-12
  • AngularJs 终极购物车(实例讲解)

    AngularJs 终极购物车(实例讲解)

    下面小编就为大家带来一篇AngularJs 终极购物车的实例讲解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • 整理AngularJS中的一些常用指令

    整理AngularJS中的一些常用指令

    这篇文章主要介绍了整理AngularJS中的一些常用指令,包括ng-app、ng-init、ng-model和ng-repeat这四个指令的讲解,需要的朋友可以参考下
    2015-06-06
  • angularjs 动态从后台获取下拉框的值方法

    angularjs 动态从后台获取下拉框的值方法

    今天小编就为大家分享一篇angularjs 动态从后台获取下拉框的值方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • AngularJs定制样式插入到ueditor中的问题小结

    AngularJs定制样式插入到ueditor中的问题小结

    这篇文章主要介绍了AngularJs定制样式插入到ueditor中的问题小结的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-08-08
  • AngularJS指令与控制器之间的交互功能示例

    AngularJS指令与控制器之间的交互功能示例

    这篇文章主要介绍了AngularJS指令与控制器之间的交互功能,结合实例形式分析了AngularJS控制器调用相关指令操作技巧,需要的朋友可以参考下
    2016-12-12
  • AngularJS内建服务$location及其功能详解

    AngularJS内建服务$location及其功能详解

    这篇文章主要为大家详细介绍了AngularJS内建服务$location及$location功能,感兴趣的小伙伴们可以参考一下
    2016-07-07

最新评论