2 回答
TA贡献1824条经验 获得超6个赞
为了让您的应用程序与服务器端渲染一起工作,我建议您不仅通过令牌使用窗口,还要以 SSR 友好的方式创建此令牌,完全不引用window。Angular 具有DOCUMENT用于访问document. 这是我为我的项目想出的window通过令牌使用的内容:
import {DOCUMENT} from '@angular/common';
import {inject, InjectionToken} from '@angular/core';
export const WINDOW = new InjectionToken<Window>(
'An abstraction over global window object',
{
factory: () => {
const {defaultView} = inject(DOCUMENT);
if (!defaultView) {
throw new Error('Window is not available');
}
return defaultView;
},
},
);
编辑:由于这是人们经常需要的东西,我们使用这种技术创建了一个带有全局对象注入令牌的小型开源库,因此您可以使用它:
https://github.com/ng-web-apis/common
它有一个姊妹库,用于在 Angular Universal 中与 SSR 一起使用的模拟:
https://github.com/ng-web-apis/universal
总体而言,请查看我们的 Angular 原生 API 中心:
https://ng-web-apis.github.io/
TA贡献1777条经验 获得超10个赞
考虑ValueProvider接口:
export declare interface ValueProvider extends ValueSansProvider {
/**
* An injection token. Typically an instance of `Type` or `InjectionToken`, but can be `any`.
*/
provide: any;
/**
* When true, injector returns an array of instances. This is useful to allow multiple
* providers spread across many files to provide configuration information to a common token.
*/
multi?: boolean;
}
该provide属性为 类型any。这意味着任何对象(包括Window构造函数)都可以进入其中。对象实际上并不重要,只有引用才重要,以确定应该使用哪个提供者在构造函数中注入参数。
使用本机构Window造函数作为注入令牌不应被视为一种好的做法。它在编译时失败,因为它Window在运行时存在于浏览器环境中,它也作为 TypeScript 存在,declare但 Angular 8 编译器无法进行静态代码分析来关联Window提供者和Window构造函数中的参数,因为赋值Window已经完成通过浏览器,而不是代码。不知道为什么它在 Angular 9 中有效,但......
您应该创建自己的表示依赖项提供程序的注入令牌。此注入令牌应该是:
一个专用的字符串(就像你做的那样'Window')
一个专用的InjectionToken。例如export const window = new InjectionToken<Window>('window');
此外,Angular 代码应该与平台无关(应该可以在浏览器和 Node.js 服务器上执行),因此最好使用返回window或undefined/的工厂null,然后在组件中处理undefined/null情况。
添加回答
举报