【问题标题】:angular4 document and window are undefinedangular4 文档和窗口未定义
【发布时间】:2018-03-02 14:18:35
【问题描述】:

我正在使用带有 angular 4 和 webpack 配置的 dot net core。

当我尝试在组件或服务中获取窗口或文档时,我收到此错误:

ReferenceError: 文档未定义

ReferenceError: 未定义窗口

这是我得到的错误:

Microsoft.AspNetCore.NodeServices[0]
      ERROR { ReferenceError: window is not defined
          at _window (C:\gitRepose\AngularCore\FM\FMWebApp\FootballWebApp\ClientApp\dist\main-server.js:30801:12)

Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
      An unhandled exception has occurred: window is not defined
      ReferenceError: window is not defined
    at _window (C:\gitRepose\AngularCore\FM\FMWebApp\FootballWebApp\ClientApp\dist\main-server.js:30801:12)

我还是 webpack 的新手,有谁知道我该如何解决这个问题? 当窗口调整大小时,我需要窗口来处理。

编辑...

我设法通过从 index.cshtml 中删除预渲染来解决这个问题

我从这里改变了它:

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

到这里:

<app>Loading...</app>

但现在显然不会在服务器端进行预渲染:/ 因此它会减慢应用程序的启动时间,有什么想法可以在不丢失服务器端预渲染的情况下解决这个问题吗?

【问题讨论】:

标签: javascript angular webpack .net-core


【解决方案1】:

如果您使用服务器端渲染,您应该删除所有使用windowdocument 在节点中运行的代码,因为节点没有这些变量(节点只有global)。

如果你还想在node env中使用windowdocument,可以尝试使用jsdom(https://github.com/tmpvar/jsdom)。

【讨论】:

  • 你知道我应该如何在我的 webpack 配置中设置 JSDOM 吗?或者你有什么有用的链接?
  • 你不需要将 jsdom 添加到 webpack 的配置中。你只需要在你的节点中使用它:github.com/tmpvar/jsdom
  • @fattikus 你可以阅读它的文档,因为如何使用取决于你想要什么。但是在我的可选中,你不需要在服务器端渲染中使用window
【解决方案2】:

如果您想使用 AOT,请使用依赖注入将窗口挂载到您的组件中。总之,写一个可以提供窗口对象的服务:

import { Injectable } from '@angular/core';

function getWindow (): any {
    return window;
}

@Injectable()
export class WindowRefService {
    get nativeWindow (): any {
        return getWindow();
    }
}

更多信息here

【讨论】:

  • 需要windows的代码在另一个库/npm包中,不在我的代码中。
【解决方案3】:

如果您想快速修复: 将此代码放在打字稿文件的顶部:

 declare var window;
 declare var document;

但如果你想做正确的事:

 import { DOCUMENT } from '@angular/platform-browser';
 export const WINDOW           = new InjectionToken( 'WINDOW' );

 @Component()
 export class YourComponent{
          constructor(
              @Inject( WINDOW ) private window,
              @Inject( DOCUMENT ) private document){}

在你的模块内:

providers       : [
    {
        provide  : WINDOW,
        useValue : window
    }
],

这样您就可以在测试和其他任何地方覆盖窗口和文档。

【讨论】:

  • 不,不是我的代码需要窗口和文档,而是从 npm 包安装的代码
  • 问题是webpack的预渲染/我使用的是dot net core
【解决方案4】:

包装你的代码,它取决于下面的窗口

if (typeof window !== 'undefined') {
    // your client-only logic here like below
    alert(window.innerWidth);
}

【讨论】:

  • 这不是解决方案,因为我需要导入使用文档/窗口的 UI 库
  • 你可以在客户端导入你的ui库
【解决方案5】:

在服务器端 JavaScript 在没有窗口或文档对象的节点环境中运行。当您的 javascript 代码在浏览器环境中执行时,Window & Document 对象起作用。所以请确保窗口或文档对象相关的代码不会在服务器端执行

如果您确实需要使用窗口或文档对象,可以使用node-jsdom (https://www.npmjs.com/package/node-jsdom)。只需安装

$ npm install node-jsdom 

Here (https://github.com/darrylwest/node-jsdom) 你会得到关于 node-jsdom 的帮助

【讨论】:

    【解决方案6】:

    我正在使用 Angular 4 应用程序并使用以下方法注入窗口对象:

    在组件constructor( @Inject('Window') private window: Window) { }

    在模块中:providers: [{ provide: 'Window', useValue: window }]

    然后在组件函数中我像这样使用它:this.window

    【讨论】:

    • 需要windows的代码在另一个库/npm包中,不在我的代码中。
    【解决方案7】:

    放置您的窗口。 componentDidMount 函数中的相关代码。

    【讨论】:

    • componentDidMount 与反应有关吗?或 webpack
    • 他在使用角度不反应!
    • 在angular4中,可以使用另一个hook:ngAfterViewChecked()
    • @user8335505 但是,当使用使用文档和窗口的库(ui 库,如 ngx 数据网格或 ng zorro)时,我将如何做到这一点?它仍然不是解决方案
    【解决方案8】:

    Index.htmlIndex.cshtml

    改变

    <app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>
    

    <app asp-ng2-prerender-module="ClientApp/dist/main-server">Loading...</app>
    

    如果您在 aspnetcore 中使用 angular4,它应该可以正常工作

    【讨论】:

      猜你喜欢
      • 2022-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-13
      • 2017-10-01
      • 2020-09-13
      • 2017-01-27
      • 1970-01-01
      相关资源
      最近更新 更多