使用ES6导入时,“jQuery未定义”

时间:2016-02-12 09:09:31

标签: javascript jquery ecmascript-6 jquery-plugins browserify

我的代码:

import $ from 'jquery'
import jQuery from 'jquery'
import owlCarousel from '../../node_modules/owlcarousel/owl-carousel/owl.carousel'

class App {
    …
    _initSlider() {
        $("#partners-carousel").owlCarousel();
    }
}

我在浏览器控制台中“未定义jQuery”。怎么了? 我可以在这个类的方法中使用jQuery作为$,但不能使用名称'jQuery'。

2 个答案:

答案 0 :(得分:14)

根据 this comment 并将其应用于您的案例,当您这样做时:

import $ from 'jquery'
import jQuery from 'jquery'

您实际上并未使用命名导出。

  

问题在于,当您执行import $ ...import jQuery ...然后import 'owlCarousel'(取决于jQuery)时,即使您声明{window.jQuery = jquery,也会对其进行评估。导入jquery后立即1}}。这是ES6模块语义与CommonJS要求的不同之处。

解决这个问题的一种方法是改为:

创建文件jquery-global.js

// jquery-global.js
import jquery from 'jquery';
window.jQuery = jquery;
window.$ = jquery;

然后将其导入主文件中:

// main.js
import './jquery-global.js';
import 'owlCarousel' from '../../node_modules/owlcarousel/owl-carousel/owl.carousel'

class App {
  ...
  _initSlider() {
    $("#partners-carousel").owlCarousel();
  }
}

这样可以确保在加载jQuery之前定义owlCarousel全局。

答案 1 :(得分:1)

@Serge 您应该在问题中提到您正在使用 browserify 和 babelify 来捆绑/转译您的代码(我从评论中知道),这将帮助人们找到您问题的正确答案。

自 2021 年起,ECMA2015+/ES6+ 不允许在浏览器中原生使用 import-maps/bare-module-path。所以基本上你不能直接在浏览器中执行以下操作,因为浏览器的行为不像 nodejs,它不知道如何/从哪里获取脚本源,你不能只是说:

import $ from 'jquery'  
import jQuery from 'jquery'

但是,您可以借助 WebPack 之类的捆绑器来完成此操作,它为在浏览器中使用 import-maps/bare-module-path 打开了大门。此外,huge work is currently being done 支持在浏览器中直接实现import-maps,无需打包器,但目前还没有实现。我知道这个问题对于 OP 来说已经足够老了,但总的来说,您可以使用 WebPack 来捆绑您的代码并按照您提到的方式导入您的依赖项。

P.S. 关于 @egel 在 2016 年 10 月提出的答案(这是当时解决方案有限的旧答案),有些人要求进行更多说明。请注意 Nicolás Bevacqua 关于 ES6+ 模块范围的以下声明:

<块引用>

ES6 模块中的声明作用域为该模块。这意味着在模块内声明的任何变量都不能用于其他模块,除非它们作为模块 API 的一部分显式导出(然后导入到想要访问它们的模块中)。

ES6+ 模块系统很棒并且使事情更有条理,但是我们能否在不需要打包器/转译器的情况下在浏览器中完全实现 ES6+ 模块?这是一个棘手的问题。当您的某些 JavaScript 依赖项只是不支持 ES6+ 模块系统的旧/经典脚本,并且不使用 export 关键字为您导出函数/值时,事情可能会变得更加困难。在这里,开发人员倾向于做一些变通方法来解决手头的问题。 window 对象用于附加函数/变量,以便在所有模块中使用它们。此处 window 对象用作在代码库中跨不同模块传输功能/数据的载体,但这不是推荐的方法。

以下引用自javascript.info

<块引用>

如果我们真的需要制作一个窗口级别的全局变量,我们可以显式地将它分配给window,并以window.user的身份访问。 但这是一个需要充分理由的例外。