【问题标题】:How to import bootstrap-daterangepicker in Angular 4 project?如何在 Angular 4 项目中导入 bootstrap-daterangepicker?
【发布时间】:2018-03-22 13:05:57
【问题描述】:

我尝试按照 this 教程中的说明将 bootstrap-daterangepicker 集成到我的 Angular 4 项目中,但我收到以下错误和警告。错误行是:Uncaught TypeError: __webpack_require__.i(...) is not a function。有人知道如何解决这个问题吗?

【问题讨论】:

标签: javascript angular typescript webpack angular-cli


【解决方案1】:

问题在于教程使用了无效的 ESM -> CommonJS 互操作。请改用import $ from jQuery;。在 ECMAScript 中调用命名空间导入 (* as) 无效。

TLDR:写

import $ from 'jquery';
import 'bootstrap-daterangepicker';

并设置--allowSyntheticDefaultImports("allowSyntheticDefaultImports": true in "compilerOptions")以便 TypeScript 正确使用合成的默认导入对代码进行类型检查。

我也在文章中添加了a comment to that effect。

详情:

基本上,ECMASCript 规范禁止将Module Namespace Objects 作为函数调用。当你使用语法时

import * as imported from 'some-module';

创建了一个名为 imported 的模块命名空间对象。此对象公开指定模块的每个导出以进行合格访问,例如imported.a,其中a 由'some-module' 导出。但是,在仅导出单个值的 AMD 或 CommonJS 模块中,通常将此值导出为 模块本身。这通常写成

// AMD
define(function () {
  const $ = {...}; // jquery implementation

  return $;
});

或者

// CommonJS
const $ = {...}; // jquery implementation

module.exports = $;

define 返回的值或分配给module.exports 的值代表模块本身。

要导入这样的导出,通常会这样写

// AMD
define(["jquery"], function ($) {
  $('div').text('set via jQuery');
});

或者

// CommonJS
const $ = requere("jquery");
$('div').text('set via jQuery');

将其与通常写为的命名导出进行比较

// AMD
define(function () {
  const $ = {...}; // jquery implementation

  return {$};
});

或者

// CommonJS
const $ = {...}; // jquery implementation

module.exports.$ = $;

要导入这样的导出,通常会这样写

// AMD
define(["jquery"], function ($) {
  $.$('div').text('set via jQuery');
});

或者

// CommonJS
const $ = require("jquery");
$.$('div').text('set via jQuery');

现在回到 ES 模块世界,* as 语法将命名的导出绑定聚合到一个对象中,以进行点 (.) 访问。

与 AMD 和 CommonJS 模块形成鲜明对比的是,在 ES 模块中,导出的所有内容都必须以 名称 导出。

然而,在 ES 模块中仍然通过 default 导出/导入语法和语义提供了导出和导入表示模块本身的单个值的实用性和简单性。该语法是

// ESM
const something = {...};
export default $;

并且通常被用作

// ESM
import $ from 'some-module';

这在概念上类似于分配给 module.exports 或从 define 返回单个值,但实际上,default 不是匿名的,它是一个导出命名 default。

所以问题就变成了,当我们有一个 AMD 或 CommonJS 模块导出一个值 as 模块本身(通常使用上述模式之一)时,我们如何将它导入到 ES模块? require 对我们不可用。我们不能导入没有名称的东西。很好的互操作,虽然有些变化是使module.exports 的值或define 返回的值作为default 导出可用。这带来了许多问题,但它允许我们编写

import $ from 'jquery';

这是可行的,因为 default 只是一个名为 default 的导出可以被调用。不能调用命名空间。

不幸的是,由于 ES 模块规范的波动、每次指定互操作机制的不确定性以及各种历史原因,TypeScript 在历史上走上了不同的道路,采取了

import * as imported from 'some-module';

暗示

const imported = require('some-module');

在类型级别。此外,它尚未自动提供导出为 AMD 和 CommonJS 模块的值作为 default,这意味着正确的语法可能在运行时失败。

然而,TypeScript 正在解决这个问题。

同时,如果你使用 SystemJS 或 Webpack 3 等模块互操作感知工具,你可以正确编写

import imported from 'some-module';

今天在 TypeScript 中。 指定 --allowSyntheticDefaultImports 编译器选项,以针对 AMD 或 CommonJS 模块启用此语法的正确类型检查。

【讨论】:

  • 嗨@Aluan,感谢您的回复。我尝试了你的建议,但现在有一个不同的错误:ERROR in C:/Users/.../app.component.ts (6,8): Module ''jquery'' has no default export。 Jquery 实际上与 import * as $ from 'jquery';Any 工作正常吗?
  • 我还尝试了import daterangepicker from 'bootstrap-daterangepicker';,而不是该教程中建议的require('bootstrap-daterangepicker');。还有一个不同的错误,即 daterangepicker 不是函数:ERROR TypeError: __WEBPACK_IMPORTED_MODULE_4_jquery__(...).daterangepicker is not a function
  • 你错过了--allowSyntheticDefaultImports 见我回答的最后一行。将其添加到您的tsconfig。
  • import daterangepicker from 'bootstrap-daterangepicker'; 不起作用,因为 datepicker 模块不导出 任何东西,它会改变 'jquery' 模块。按照教程中的说明使用import 'bootstrap-daterangepicker';。
  • @AIuan,感谢您的回复。我尝试了两种更改,jquery 再次工作,但我回到了屏幕截图中提到的第一个错误
猜你喜欢
  • 2018-12-09
  • 2018-04-09
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-21
相关资源
最近更新 更多