Angular Universal和浏览器功能检查

Cob*_*ger 5 javascript feature-detection typescript angular

在使用jQuery或普通JavaScript开发Web应用程序时,首先检查功能可用性是很常见的.因此,例如,如果我想使用该document.oncopy事件,我应该首先使用这样的东西来确保我的代码不会破坏较小的浏览器:

if ("oncopy" in document) {
  // Feature is available
}
Run Code Online (Sandbox Code Playgroud)

我对Angular2中的工作原理有点疑惑.如果我希望只在浏览器中运行,我仍然可以使用相同的,但我特别告诉我,如果我想使用Angular Universal并依赖于模板或DomRenderer,则不要使用DOM.这允许页面在服务器上预呈现,并提供真正令人印象深刻的性能增益.

但是假设我想要一个特定的div,如果document.oncopy它不可用则不可见.我的理解是不建议这样做:

<div *ngIf="hasFeature()">...</div>
Run Code Online (Sandbox Code Playgroud)

hasFeature() {
  return 'oncopy' in document;
}
Run Code Online (Sandbox Code Playgroud)

因为那时我还在操纵DOM.请注意,我的示例是关于document.oncopy但我可以选择任何没有普遍支持的功能.

我使用Chris Nwamba关于Scotch 的教程对此进行了测试,并将以下内容添加到他的Home模板的末尾:

<div *ngIf="hasFeature()">Feature is supported</div>
<div *ngIf="!hasFeature()">Feature is NOT supported</div>
Run Code Online (Sandbox Code Playgroud)

更新:有趣的是,它在不同的浏览器上给出了不同的结果.在Chrome 55上,它按正常方式执行,并显示"功能受支持"消息.在IE11上,我收到了"不支持"的消息.在这两个实例中,服务器日志都显示一条EXCEPTION: document is not defined消息,但页面看起来仍然完全正常.

那么,如果我想使用Angular Universal,检查浏览器功能的正确方法是什么?

更新: 我还玩弄模板中的字段并从其中一个生命周期钩子中分配该字段.ngAfterContentInit似乎是一个很好的候选人,但也导致服务器上的错误.它在浏览器中运行良好,没有奇怪的效果(到目前为止我已经注意到了).

Cob*_*ger 1

有两种方法可以解决这个问题:

  1. 仅在服务器完成渲染并且客户端完全初始化(包括由 完成的用户事件重放preboot.js)后才进行检查。
  2. 当页面在服务器上运行时返回合理的默认值,并仅在浏览器中执行实际检查。

我开始考虑第一个选项,但 Angular2 生命周期事件都无济于事。事实上,您可以清楚地看到它们都在服务器上执行,然后才在客户端上执行。

然后我开始寻找可用的东西preboot.js,但很快意识到它比需要的更复杂。

所以我选择了选项2。事实证明,检查浏览器就像导入和检查一样简单isBrowser

import { isBrowser } from "angular2-universal";

@Component({
 // All the usual stuff
})
export class MyComponent {
  // ...
  hasFeature(): boolean {
    return isBrowser && 'oncopy' in document;
  }
  // ...
}
Run Code Online (Sandbox Code Playgroud)

然后使用我在问题中所示的模板。

要检查您是否在服务器上运行,请isNode以完全相同的方式导入和使用。似乎没有明显的方法来区分 Node 和 ASP.NET Core,但也许最好不要编写太多特定于平台的代码。