简体   繁体   English

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

[英]'jQuery is not defined' when use ES6 import

My code:我的代码:

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

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

I have 'jQuery is not defined' in browser console.我在浏览器控制台中有“未定义 jQuery”。 What's wrong?怎么了? I can use jQuery as $ in methods of this class, but not with name 'jQuery'.我可以在此类的方法中使用 jQuery 作为 $,但不能使用名称“jQuery”。

According to this comment and apply it to your case, when you're doing:根据此评论并将其应用于您的案例,当您执行以下操作时:

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

you aren't actually using a named export.您实际上并未使用命名导出。

The problem is that when you do import $ ... , import jQuery ... and then import 'owlCarousel' (which depends on jQuery ), these are evaluated before, even if you declare window.jQuery = jquery right after importing jquery .问题是,当您执行import $ ...import jQuery ...然后import 'owlCarousel' (这取决于jQuery )时,即使您在导入jquery后立即声明window.jQuery = jquery ,这些也会被评估。 That's one of the ways ES6 module semantics differs from CommonJS' require.这是 ES6 模块语义与 CommonJS 的 require 不同的方式之一。

One way to get around this is to instead do this:解决这个问题的一种方法是这样做:

Create file jquery-global.js创建文件jquery-global.js

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

then import it in you main file:然后在你的主文件中导入它:

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

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

That way you make sure that the jQuery global is defined before owlCarousel is loaded.这样您就可以确保在加载owlCarousel之前定义了jQuery全局owlCarousel

@Serge You should have mentioned in your question that you are using browserify & babelify to bundle/transpile your code (I knew it from comments), this will help people find the correct answer to your question. @Serge 你应该在你的问题中提到你正在使用 browserify 和 babelify 来捆绑/转换你的代码(我从评论中知道),这将帮助人们找到你问题的正确答案。

As of 2021, ECMA2015+/ES6+ don't allow the use of import-maps/bare-module-path natively in the browser.截至 2021 年,ECMA2015+/ES6+ 不允许在浏览器中原生使用import-maps/bare-module-path So basically you can't do the following directly in the browser, because the browser doesn't behave like nodejs, it doesn't understand how/where to fetch for the source of your scripts, you can't just say:所以基本上你不能直接在浏览器中执行以下操作,因为浏览器的行为不像 nodejs,它不了解如何/从哪里获取脚本源,你不能只说:

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

However, you can do this by the help of bundlers like WebPack which opens that door for import-maps/bare-module-path to be used in the browser.但是,您可以借助 WebPack 之类的捆绑器来完成此操作,它为要在浏览器中使用的import-maps/bare-module-path打开了大门。 Besides, huge work is currently being done to support the implementation of import-maps directly in the browser without the need of bundlers, but it's not implemented yet.此外,目前正在做大量的工作来支持直接在浏览器中实现导入映射,而不需要打包器,但还没有实现。 I know that this question is old enough for the OP to follow, but in general, you can use WebPack to bundle your code and import your dependencies the way you mentioned.我知道这个问题对于 OP 来说已经足够老了,但总的来说,您可以使用 WebPack 来捆绑您的代码并按照您提到的方式导入您的依赖项。

PS Regarding the answer proposed by @egel in Oct 2016 (which is an old answer with limited solutions at that time) some people asked for more clarifications. PS关于@egel在 2016 年 10 月提出的答案(这是当时解决方案有限的旧答案),有些人要求进行更多说明。 Please note the following statement by Nicolás Bevacqua regarding the scope of ES6+ modules:请注意Nicolás Bevacqua关于 ES6+ 模块范围的以下声明:

Declarations in ES6 modules are scoped to that module. ES6 模块中的声明适用于该模块。 That means that any variables declared inside a module aren't available to other modules unless they're explicitly exported as part of the module's API (and then imported in the module that wants to access them).这意味着在模块内声明的任何变量都不能用于其他模块,除非它们作为模块 API 的一部分显式导出(然后导入到想要访问它们的模块中)。

ES6+ module system is awesome and makes things much more organized, but can we fully implement ES6+ modules in the browser without the need of bundlers/transpilers? ES6+ 模块系统很棒并且使事情更有条理,但是我们可以在浏览器中完全实现 ES6+ 模块而不需要打包器/转译器吗? This is a tough question.这是一个棘手的问题。 Things may get harder when some of your JavaScript dependencies are just old/classic scripts that do not support the ES6+ modules system, and do not use the export keyword to export functions/values for you.当您的某些 JavaScript 依赖项只是不支持 ES6+ 模块系统的旧/经典脚本,并且不使用export关键字为您导出函数/值时,事情可能会变得更加困难。 Here, developers tend to do some workarounds to solve the problem in hand.在这里,开发人员倾向于做一些变通方法来解决手头的问题。 The window object is used to attach functions/variables in order to use them across all modules. window对象用于附加函数/变量,以便在所有模块中使用它们。 Here the window object is used as a carrier to transfer functions/data across different modules within your code base, and this is not a recommended approach though.在这里,窗口对象用作在代码库中的不同模块之间传输功能/数据的载体,但这不是推荐的方法。

Below is quoted from javascript.info :以下引用自javascript.info

If we really need to make a window-level global variable, we can explicitly assign it to window and access as window.user.如果我们真的需要制作一个窗口级别的全局变量,我们可以将它显式分配给window并以window.user的身份访问。 But that's an exception requiring a good reason.但这是一个需要充分理由的例外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM