Webpack:如何使角度自动检测jQuery并将其用作angular.element而不是jqLit​​e?

Bor*_*kov 39 jquery angularjs webpack

我正在使用Webpack构建一个Angular 1.4项目.该项目使用了几个jQuery插件,这些插件包含在angular指令中.那些指令在内部使用angular.element,可能暗示angular.element是真正的jQuery,而不是jqLit​​e.

我想使用angular来自动检测jQuery并使用它代替jqLit​​e.我试图在我的入口点模块中本地需要jquery app.js:require('jquery')并使用全局公开jQuery require(expose?$!expose?jQuery!jquery).

不过,无论我做什么,都angular.element指的是jqLit​​e.


我的研究得出了一些结论:

  1. 即使作为CommonJS模块导入,Angular也会将自己分配给一个全局变量window.angular,所以我不需要expose使用Webpack:当作为CommonJS模块加载时,Angular会将自身全局分配给`window.angular`吗?.
  2. ProviderPlugin似乎没有做到这一点:它没有将jQuery暴露给全局命名空间; 相反,对于依赖于全局名称jQuery的每个模块,它都会插入require('jquery')其中.我不是100%肯定,但看起来像角不访问jQuery直接,相反,它试图访问从全局命名空间window.jQuerybindJQuery的功能,所以这也是没有办法:暴露了jQuery用的WebPack真正的Window对象.
  3. 出于与ProviderPlugin相同的原因,imports-loader似乎不合适:Angular想要window.jQuery,而不仅仅是jQuery.
  4. 使用expose-loader,jquery使它成为窗口对象.我的问题是,Babel将其所有导入提升到生成的代码中的模块顶部.因此,虽然在源文件require(expose?jquery!jquery)之前,但是在jquery之前import angular from "angular",bundle require("angular")中位于文件的顶部,因此在导入Angular时,jquery尚不可用.我想知道,如何使用带有ECMA6导入语法的Webpack加载器.
  5. 有人建议使用import语法而不是require语法与jquery:import "jquery"或者import $ from "jquery",不是require(jquery):(Petr Averyanov:如何使用ECMAScript 6导入的Webpack加载器语法(导入/导出/公开)?).jquery源代码包装有一个特殊的包装器,它确定了如何需要jquery(使用AMD/require,CommonJS或global with <script>语句).基于此,它noGlobal为jquery结构设置一个特殊参数,并window.jQuery根据其值创建或不创建noGlobal.在jQuery 2.2.4,在import "jquery" noGlobal === truewindow.jQuery没有创建.IIRC,一些旧版本的jquery没有识别import为CommonJS导入,并将imported jquery 添加到全局命名空间,这允许使用angular.

细节:这是我的app.js:

'use strict';

require("expose?$!expose?jQuery!jquery");
require("metisMenu/dist/metisMenu");
require("expose?_!lodash");
require("expose?angular!angular");

import angular from "angular";
import "angular-animate";
import "angular-messages";
import "angular-resource";
import "angular-sanitize";
import "angular-ui-router";
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.css";
import "angular-bootstrap";

require("../assets/styles/style.scss");
require("../assets/fonts/pe-icon-7-stroke/css/pe-icon-7-stroke.css");

// Import all html files to put them in $templateCache
// If you need to use lazy loading, you will probably need
// to remove these two lines and explicitly require htmls
const templates = require.context(__dirname, true, /\.html$/);
templates.keys().forEach(templates);

import HomeModule from "home/home.module";
import UniverseDirectives from "../components/directives";

angular.module("Universe", [
    "ngAnimate",
    "ngMessages",
    "ngResource",
    "ngSanitize",
    "ui.router",
    "ui.bootstrap",

    HomeModule.name,
    UniverseDirectives.name,
])
.config(function($urlRouterProvider, $locationProvider, $stateProvider){
    // $urlRouterProvider.otherwise('/');

    // $locationProvider.html5Mode(true);

    $stateProvider
      .state('test', {
        url: "/test",
        template: "This is a test"
      });
});
Run Code Online (Sandbox Code Playgroud)

小智 43

得到了john-reilly的回答:
webpack angular和jquery的神秘案例

bob-sponge的答案并不完全正确 - Provide插件实际上是对它处理的模块进行文本替换,所以我们需要提供window.jQuery(这是角度正在寻找的)而不仅仅是jQuery.

在您webpack.config.js需要将以下条目添加到您的插件:

new webpack.ProvidePlugin({
    "window.jQuery": "jquery"
}),
Run Code Online (Sandbox Code Playgroud)

本品采用的WebPack ProvidePlugin,并在webpackification点(©2016约翰·赖利)在代码中window.jQuery所有引用将到包含的jQuery的的WebPack模块的引用来代替.因此,当您查看捆绑文件时,您将看到检查window对象的代码jQuery已成为:

jQuery = isUndefined(jqName) ?
  __webpack_provided_window_dot_jQuery : // use jQuery (if present)
    !jqName ? undefined : // use jqLite
    window[jqName]; // use jQuery specified by `ngJq`
Run Code Online (Sandbox Code Playgroud)

那就对了; webpack正在为Angular提供jQuery,同时仍然 没有jQuery变量放到window.整洁吧?


Luk*_*hen 7

更新!

显然你仍然需要在ES6示例中使用commonJs require for angular.

import $ from "jquery"

window.$ = $;
window.jQuery = $;

var angular = require("angular");
Run Code Online (Sandbox Code Playgroud)

以下是原始答案



我想要一个更简单的解决方案.只需将jQuery设为全局窗口,以便angular可以识别它:

var $ = require("jquery")

window.$ = $;
window.jQuery = $;

var angular = require("angular");
Run Code Online (Sandbox Code Playgroud)

或在你的情况下(OUT DATED):

import $ from "jquery"

window.$ = $;
window.jQuery = $;

import angular from "angular";
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助 :)