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

2024-01-05

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

我希望 Angular 自动检测 jQuery 并使用它而不是 jqLit​​e。我试图在我的入口点模块中本地调用 jqueryapp.js: require('jquery')并在全球范围内公开 jQueryrequire(expose?$!expose?jQuery!jquery).

尽管如此,无论我做什么,angular.element指的是jqLit​​e。


我的研究得出了几项发现:

  1. 即使作为 CommonJS 模块导入,Angular 也会将自身分配给全局变量window.angular,所以我不需要expose与 Webpack 一起使用:当作为 CommonJS 模块加载时,Angular 是否将自己全局分配给“window.angular”? https://stackoverflow.com/questions/36101119/does-angular-assign-itself-to-window-angular-globally-when-loaded-as-commonjs/36106899#36106899.
  2. ProviderPlugin 似乎并没有解决这个问题:它没有将 jQuery 暴露给全局命名空间;相反,对于每个依赖于全局名称 jQuery 的模块,它会插入require('jquery')在里面。我不是 100% 确定,但看起来 Angular 无法访问jQuery相反,它尝试直接从全局命名空间访问window.jQuery in bindJQuery函数,所以这种方法没有帮助:使用 Webpack 将 jQuery 暴露给真实的 Window 对象 https://stackoverflow.com/questions/29080148/expose-jquery-to-real-window-object-with-webpack.
  3. 出于与 ProviderPlugin 相同的原因,imports-loader似乎不合适:Angular 想要window.jQuery, 不只是jQuery.
  4. With expose-loader,jquery 使其到达 window 对象。我的问题是 Babel 将其所有导入提升到结果代码中模块的顶部。因此,虽然require(expose?jquery!jquery)之前是import angular from "angular"在源文件中,在捆绑包中require("angular")位于文件顶部,位于 jquery 之前,因此当导入 Angular 时,jquery 尚不可用。我想知道如何使用具有 ECMA6 导入语法的 Webpack 加载器。
  5. 有人建议使用import语法而不是requirejquery 语法:import "jquery" or import $ from "jquery", not require(jquery):(彼得·阿维扬诺夫:如何在 ECMAScript 6 导入中使用 Webpack 加载器语法(导入/导出/暴露)? https://stackoverflow.com/questions/36150641/how-to-use-webpack-loaders-syntax-imports-exports-expose-with-ecmascript-6-im)。 jquery源代码是用特殊的包装纸包裹起来 https://github.com/jquery/jquery/blob/master/src/wrapper.js#L41,它标识了如何需要 jquery(使用 AMD/require、CommonJS 或全局使用<script>陈述)。在此基础上它设置了一个特殊的参数noGlobal对于 jquery 结构,或者创建window.jQuery或不,基于的价值noGlobal。从 jquery 2.2.4 开始,import "jquery" noGlobal === true and window.jQuery未创建。 IIRC,一些旧版本的jquery无法识别import作为 CommonJS 导入并添加import将 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"
      });
});

得到这个答案约翰·赖利 https://stackoverflow.com/users/761388/john-reilly:
webpack Angular 和 jquery 的神秘案例 http://blog.johnnyreilly.com/2016/05/the-mysterious-case-of-webpack-angular-and-jquery.html

海绵鲍勃 https://stackoverflow.com/users/1554165/bob-sponge的答案不太正确 - Provide 插件实际上是在它处理的模块上进行文本替换,所以我们需要提供window.jQuery(这就是 Angular 正在寻找的)而不仅仅是jQuery.

In your webpack.config.js你需要添加 您的插件的以下条目:

new webpack.ProvidePlugin({
    "window.jQuery": "jquery"
}),

这里使用了webpack提供插件 https://github.com/webpack/docs/wiki/list-of-plugins#provideplugin并且,在这一点上 webpackification (© 2016 John Reilly) 代码中的所有引用 window.jQuery 将替换为对 webpack 模块的引用 包含 jQuery。因此,当您查看捆绑文件时,您会看到 检查的代码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`

这是正确的; webpack 为 Angular 提供了 jQuery,同时仍然not放置一个jQuery变量到window。整洁吧?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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