【问题标题】:'jQuery is not defined' when use ES6 import使用 ES6 导入时“未定义 jQuery”
【发布时间】:2016-05-23 08:49:55
【问题描述】:

我的代码:

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'。

【问题讨论】:

  • 你用什么来加载/转换你的代码?
  • 浏览器和 babelify。这是 gulp 任务: gulp.task('compile', () => { return browserify( { entries: files.source.script, debug: !production, transform: [babelify.configure({ 'presets': ['es2015 '] })] } ) .bundle() .pipe(source('script.js')) .pipe(buffer()) .pipe(production ? uglify() : gutil.noop()) .pipe(gulp. dest(files.dest.scripts)).pipe(生产?gutil.noop():livereload());});
  • 如果您在浏览器中执行此操作:developer.mozilla.org/en/docs/web/javascript/reference/…
  • @Serge 你找到解决方案了吗?

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


【解决方案1】:

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

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

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

问题在于,当您执行import $ ...import jQuery ...import 'owlCarousel'(取决于jQuery)时,即使您在导入jquery 之后立即声明window.jQuery = jquery,也会对这些进行评估。这是 ES6 模块语义不同于 CommonJS 的 require 的方式之一。

解决此问题的一种方法是改为这样做:

创建文件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();
  }
}

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

【讨论】:

  • 确实可行,但您能告诉我们更多信息吗?为什么只能用您的方法保证订购?它是否记录在某处?谢谢!
  • 这似乎是对我有用的解决方案。你能解释一下为什么会这样吗?顺便说一句,非常感谢这个解决方案。
【解决方案2】:

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

自 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 的身份访问。 但这是一个例外,需要有充分的理由。

【讨论】:

    猜你喜欢
    • 2016-06-24
    • 2017-07-14
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    相关资源
    最近更新 更多