Angular 网络连接状态组件
Posted 全栈修仙之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Angular 网络连接状态组件相关的知识,希望对你有一定的参考价值。
在开发 Web 应用程序时,有时候我们需要获取当前的网络状态,然后根据不同的网络状态显示不同的提示消息或显示不同页面内容。对于原生应用、混合应用或提供 JS-SDK 的第三方平台来说,我们可以通过相关的 Network API 来获取当前的网络连接状态。但对于 Web 应用来说,虽然也有相关的 Network Information API,但兼容性并不是太好,具体的兼容情况,可以参考 Can I Use - netinfo。
Network Information API
此 API 是由 WICG 编辑的草案,目前可在 Chrome 61 以上的版本中使用。开发者可以通过navigator.connection
对象来访问与当前网络连接相关的属性:
connection.type:返回当前 User Agent 的物理网络类型,可能的值为 “cellular”,”ethernet”,”wfi” 或 “none” 等;
connection.downlink:返回基于最近观察到的活动连接的有效带宽(以 Mb/s 为单位);
connection.rtt:返回基于最近观察到的活动连接估计平均往返时间(以毫秒为单位);
connection.saveData:如果用户在其浏览器启用 “reduced data mode” 模式,则返回 true;
connection.effectiveType:返回有效的网络连接类型,可能的值为 slow-2g,2g,3g 或 4g。该值的是基于 rtt 和 downlink 的值测算出来的。
以下是网络连接类型的评估标准:
讲到这里突然想起之前看到的一篇文章 JS 检测网络带宽,有兴趣的小伙伴可以了解一下。
开发网络连接组件
通过结合 Network Information API 与 Angular,我们可以创建一个组件,实现根据不同网络连接速度渲染不同的内容。比如,当我们检测到弱网络的时候,我们可以渲染一个占位符或一个低分辨率的图片或视频,从而提高页面的加载速度。
首先,让我们把连接变化事件封装为一个 Observable 对象:
const connection$ = new Observable((observer) => {
const { effectiveType } = navigator.connection;
observer.next(effectiveType);
const onConnectionChange = () => {
const { effectiveType } = navigator.connection;
observer.next(effectiveType);
}
navigator.connection
.addEventListener('change', onConnectionChange)
return () => {
navigator.connection
.removeEventListener('change', onConnectionChange);
observer.complete();
}
});
在页面初始化和连接网络状态发生变化的时候,可观察的 connection$ 对象将会自动通知我们当前的网络连接状态。
接下来,我们来创建 ConnectionComponent 组件和相关的 Connection 指令:
connection.component.ts
@Component({
selector: 'connection',
template: `
<ng-template [ngTemplateOutlet]="fast.tpl"
*ngIf="isFast">
</ng-template> <ng-template [ngTemplateOutlet]="slow.tpl"
*ngIf="!isFast">
</ng-template> `,
})
export class ConnectionComponent {
isFast = true;
@ContentChild(FastDirective)
fast: FastDirective;
@ContentChild(SlowDirective)
slow: SlowDirective;
private subscription: Subscription;
ngOnInit() {
const connection = navigator.connection;
if (!connection) {
return;
}
this.subscription = connection$
.subscribe((effectiveType: string) => {
if (/slow-2g|2g|3g/.test(effectiveType)) {
this.isFast = false;
} else {
this.isFast = true;
}
})
}
ngOnDestroy() {
this.subscription
&& this.subscription.unsubscribe();
}
}
fast.directive.ts
@Directive({
selector: '[fast]'
})
export class FastDirective {
constructor(
public tpl: TemplateRef<any>
) { }
}
slow.directive.ts
@Directive({
selector: '[slow]'
})
export class SlowDirective {
constructor(
public tpl: TemplateRef<any>
) { }
}
在上面的示例中,ConnectionComponent 会根据 effectiveType
属性的值,然后显示 slow 或 fast 指令实例所关联的模板。现在我们来看一下如何使用:
<connection>
<ng-container *fast>
Fast connection - Render a video
</ng-container>
<ng-container *slow>
Slow connection - Render a placeholder
</ng-container>
</connection>
正如前面提到的,基于 Network Information API ,我们也可以实现一个简单的指令,根据不同的网络状态显示不同分辨率的图片。
<img connection
slowSrc="https://via.placeholder.com/350x150?text=slow"
fastSrc="https://via.placeholder.com/350x150?text=fast">
对应的 connection 指令的具体实现如下:
import { Directive, Attribute, ElementRef } from '@angular/core';
@Directive({
selector: '[connection]'
})
export class ConnectionDirective {
constructor(
@Attribute('slowSrc')
private slowSrc,
@Attribute('fastSrc')
private fastSrc,
private host: ElementRef<htmlImageElement>
) {
}
ngOnInit() {
const { effectiveType } = navigator.connection;
let src;
if (/slow-2g|2g|3g/.test(effectiveType)) {
src = this.slowSrc;
} else {
src = this.fastSrc;
}
this.host.nativeElement.setAttribute('src', src)
}
}
查看线上完整的示例:Stackblitz
总结
本文是在过完 “10·24 — 爱码士” 节后,参考 connection-aware-components-in-angular 这篇文章整理的。其中主要介绍了 Network Information API 涉及的相关属性及每个属性的作用。对于使用 Ionic 或 Cordova 项目来说,可以使用 cordova-plugin-network-information 这个库来获取网络信息,有需要的小伙伴可以了解一下。
参考资源
connection-aware-components-in-angular
connection-aware-components
以上是关于Angular 网络连接状态组件的主要内容,如果未能解决你的问题,请参考以下文章
如何保存底部导航片段的状态 - 具有单个导航图的 Android 导航组件
当返回到“导航架构组件”中的同一选项卡时,嵌套片段的状态会丢失