Using TransferState API in an Angular v5 Universal App

让我们用一个具体的例子来说明这篇文章。 我们有一个天气应用程序,在其侧边栏中显示城市列表。 当您单击城市名称时,该应用程序会显示该城市的当前天气。

因为我们希望我们的应用程序是可抓取和可索引的,所以我们使它通用:城市页面在服务器上呈现,存储为 HTML 文件并由 HTTP 服务器提供服务。 这些页面将包含浏览器应用程序,因此用户可以在加载第一页后使用 Angular 的强大功能继续在应用程序中导航。

您可以按照以下步骤尝试这个简单的示例。

使用下列命令将这个例子 clone 到本地:

$ git clone https://github.com/feloy/ng-demo-transfer-state
$ cd ng-demo-transfer-state
$ git checkout initial

构建程序:

$ npm install
$ ng build -prod
$ ng build -prod -app server --output-hashing=none

为不同的城市创建不同的页面:

$ node render-page.js /Paris > dist/Paris
$ node render-page.js /London > dist/London
$ node render-page.js /San%20Fransisco > 'dist/San Fransisco'

您现在可以使用首选的 HTTP 服务器为 dist 目录提供服务。

现在,如果您直接访问页面 http://your-domain/Paris(这是访问者来自搜索引擎的典型情况),您可以观察到页面闪烁 - 这是因为内容已经存在并且已经下载到本地了,然后浏览器应用程序会重新加载并再次显示。

TransferState to the rescue

Angular v5 中引入的 TransferState API 可以帮助解决这种情况。 它可以将数据从应用程序的服务器端传输到浏览器应用程序。
为此,服务器应用程序将在它生成的 HTML 页面中添加我们要传输的数据。
包含在此生成的 HTML 页面中的浏览器应用程序将能够读取此数据。

在这个分支查看解决方案。

$ git checkout transfer-data

首先在服务器应用上导入 ServerTransferStateModule,在浏览器应用上导入 BrowserTransferStateModule:

// src/app/app.server.module.ts
import {ServerTransferStateModule} from '@angular/platform-server';
[...]
@NgModule({imports: [AppModule,ServerModule,ServerTransferStateModule],bootstrap: [AppComponent],
})
export class AppServerModule {}
// src/app/app.module.ts
import { BrowserTransferStateModule } from '@angular/platform-browser';
[...]
@NgModule({declarations: [AppComponent, CityComponent],imports: [BrowserModule.withServerTransition({ appId: 'ng-demo-transfer-state-app' }),BrowserTransferStateModule,[...]

现在,在为组件提供数据的解析器中,我们可以使用 TransferState API:

  • 在服务器上,我们首先注册 onSerialize 以提供我们将下载的数据,然后我们从我们的数据提供者那里获取数据,这里是一个 HTTP GET 请求。
  • 在浏览器上,我们使用get方法来获取server提供的数据,我们直接提供这些数据。 我们还从传输状态中删除了提供的数据,因此页面的重新加载将不再使用提供的数据。

我们可以通过调用 hasKey 方法来检测我们是在服务器上还是在浏览器应用程序上。 此方法仅在浏览器中返回 true。

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<CityWeather> {const found = this.transferState.hasKey(RESULT_KEY);if (found) {const res = Observable.of(this.transferState.get<CityWeather>(RESULT_KEY, null));this.transferState.remove(RESULT_KEY);return res;} else {this.transferState.onSerialize(RESULT_KEY, () => this.result);const name = route.params['city'];return this.http.get<CityWeather>('https://api.openweathermap.org/data/2.5/weather?q=' + name + '&units=metric&APPID=' + this.key).do(result => this.result = result);}}

因为我们是调用remove方法移除提供的数据,所以浏览器显示的以下页面会调用onSerialize方法,但是这个方法没有效果,因为toJson只在服务端调用。

一个更清晰的解决方案是使用 isPlatformServer 和 isPlatformBrowser 方法来检测平台并采取相应的行动。

更多Jerry的原创文章,尽在:“汪子熙”:

使用 Angular Transfer State 的一个具体例子相关推荐

  1. Angular里ngClass的一个使用例子

    ngClass定义的位置: export declare class NgClass implements DoCheck {private _iterableDiffers;private _key ...

  2. Angular路由开发的一个实际例子

    生成一个新的Component: 在NgModule文件app.module.ts里,找到RouterModule.forRoot, 新增一条路由信息: 这条路由信息将url同Component Pr ...

  3. SAP 电商云 Spartacus UI Proxy Facade 的一个实际例子

    如何理解 SAP 电商云 Spartacus UI 中的 proxy facade? Jerry 这篇文章什么是 SAP 电商云 Spartacus UI 的 proxy façade提供了理论上的解 ...

  4. 一个简单例子:贫血模型or领域模型

    转:一个简单例子:贫血模型or领域模型 贫血模型 我们首先用贫血模型来实现.所谓贫血模型就是模型对象之间存在完整的关联(可能存在多余的关联),但是对象除了get和set方外外几乎就没有其它的方法,整个 ...

  5. SAP MM采购定价过程的一个简单例子

    SAP MM采购定价过程的一个简单例子 本文以一个简单的例子阐述了SAP MM模块中采购定价的基本原理.本例中,假定采购订单里输入的是含税采购价,然后系统自动计算出物料最终的采购价格(含税价-税额=采 ...

  6. 用一个实际例子理解Docker volume工作原理

    要了解Docker Volume,首先我们需要理解Docker文件系统的工作原理.Docker镜像是由多个文件系统的只读层叠加而成.当一个容器通过命令docker run启动时,Docker会加载只读 ...

  7. 决策树的构造——一个手工例子

    决策树的构造--一个手工例子 这个数据集来自Mitchell的机器学习,叫做是否去打网球play-tennis,以下数据仍然是从带逗号分割的文本文件,复制到纪事本,把后缀直接改为.csv就可以拿Exc ...

  8. 一个ioc例子jdk和spring版本导致问题

    今天橘子松在做一个简单例子的时候,出现bug让我久久找了半小时... 天啊 不会吧 错误如下:   java.lang.NoSuchMethodError: org.springframework.a ...

  9. 用一个实际例子理解Docker volume工作原理 1

    要了解Docker Volume,首先我们需要理解Docker文件系统的工作原理.Docker镜像是由多个文件系统的只读层叠加而成.当一个容器通过命令docker run启动时,Docker会加载只读 ...

最新文章

  1. android 在 ListView 的 item 中插入 GridView 仿微信朋友圈图片显示。
  2. Smartform 动态打印选择屏幕上传的图片
  3. PaddlePaddle飞浆开启人工智能新时代
  4. Dynamips 简介
  5. 几个简单的排序方式1
  6. zookeeper入门系列
  7. 像阿超那样,花20分钟写一个能自动生成小心四则运算题目的 “软件”,要求:除了整数以外,还要支持真分数的四则运算。 和同学们比较一下各自程序的功能,实现方法的异同,等等...
  8. Unity2020.1新功能探路:编辑器相关更新
  9. 用python爬取图片和搞笑段子
  10. 转:初学shell脚本--shell语法使用
  11. 编译安装vlmcsd
  12. 重学前端第一天——HTML结构和常见的HTML元素
  13. u盘在计算机打不开,别的电脑能打开u盘自己的怎么打不开解决方法
  14. Centos7上使用Kind搭建Kubernetes环境
  15. 关于 蓝天显卡 异形卡 的改inf文件上驱动说明
  16. HLA高层体系结构+RTI(2)
  17. Received empty response from Zabbix Agent at [agent]. Assuming that agent dropped connection because
  18. 老人与海好词100英文带翻译_老人与海优美段落英文,英文的优美句子,带翻译,越多越好,谢谢...
  19. 大批程序员可能面临被劝退!
  20. [bzoj1812][IOI2006]riv_多叉树转二叉树_树形dp

热门文章

  1. ES6-note-Set和Map(草稿)
  2. Linux Load Balancing之NAT与DR模型
  3. [Visual Studio] 未能完成操作 不支持此接口
  4. WIN8 打开图片内置管理员无法激活此应用
  5. precision recall
  6. scheme 学习:pair 和 list
  7. petshop详解之一:PetShop的系统架构设计
  8. 15 FFT及其框图实现
  9. Linux命令更新系统时间,更新所有文件的时间(转)
  10. 【Android】Theme.AppCompat.Light 问题