简体   繁体   English

使用RequireJS通过填充程序加载Highcharts并保持jQuery依赖性

[英]Loading Highcharts via shim using RequireJS and maintaining jQuery dependency

I'm attempting to load the Highcharts library using a shim in RequireJS. 我正在尝试使用RequireJS中的填充程序加载Highcharts库。 However, when Highcharts loads, it throws an exception because it can't access the jQuery methods it depends on. 但是,当Highcharts加载时,它会抛出异常,因为它无法访问它所依赖的jQuery方法。

The require config looks like so: require配置如下所示:

require.config({
    baseUrl: "js",

    shim: {

        'libs/highcharts/highcharts.src.js': {
            deps: ['jquery'],
            exports: function(jQuery)
            {
                this.HighchartsAdapter = jQuery;

                return this.Highcharts;
            }
        }
    }
});

The exception that is thrown is: 引发的异常是:

Uncaught TypeError: undefined is not a function

and is in regards to this line: 并且就这条线而言:

dataLabels: merge(defaultLabelOptions, {

The issue is the merge call, which eventually maps itself back to jQuery (or some other adapter that Highcharts supports; but I'm just using jQuery). 问题是merge调用,它最终将自身映射回jQuery(或Highcharts支持的其他适配器;但我只是使用jQuery)。

I'm not sure exactly how to make sure Highcharts gets access to jQuery using RequireJS and shim. 我不确定如何确保Highcharts使用RequireJS和shim访问jQuery。

Has anyone used RequireJS and Highcharts together before? 有没有人之前一起使用过RequireJS和Highcharts? I guess the issue isn't specific to highcharts, but any library that has other sorts of dependencies. 我想问题不是特定于highcharts,而是任何具有其他种类依赖关系的库。

Thanks in advance for any advice or points to the correct direction! 提前感谢任何建议或指向正确的方向!

To add further context, in hopes that someone who is familiar with require.js or shims will be able to help without having to be too intimately familiar with highcharts, here's some source that sets up this merge method in Highcharts 为了增加更多的上下文,希望熟悉require.js或shims的人能够提供帮助,而不必过于熟悉highcharts,这里有一些在Highcharts中设置这种merge方法的来源

var globalAdapter = win.HighchartsAdapter,
adapter = globalAdapter || {},

// Utility functions. If the HighchartsAdapter is not defined, 
// adapter is an empty object
// and all the utility functions will be null. In that case they are 
// populated by the
// default adapters below.

// {snipped code}

merge = adapter.merge

// {snipped code}

if (!globalAdapter && win.jQuery) {
    var jQ = win.jQuery;

    // {snipped code}

    merge = function () {
        var args = arguments;
        return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
    };

    // {snipped code}
}

The win object is a reference set up to window at the beginning of the script. win对象是在脚本开头设置window的引用。 So, I thought adding window.jQuery = jQuery; 所以,我想添加window.jQuery = jQuery; to the export method on the shim would result in highcharts picking up the jQuery reference; 在shim上的导出方法会导致highcharts获取jQuery引用; but it didn't. 但事实并非如此。

Again, any insight, info, advice, or heckles would be appreciated at this point - I'm at a complete loss, and starting to question whether trying to implement and AMD package system in browser javascript is even worth it. 再一次,任何见解,信息,建议或哎呀都会受到赞赏 - 我完全失去了,并开始质疑是否尝试实现和浏览器javascript中的AMD包系统是否值得。


After accepting the answer from pabera below I thought it appropriate to update my question to reflect how his answer helped my solution (though, it's basically his answer). 在接受了下面pabera的回答后,我认为更新我的问题以反映他的答案如何帮助我的解决方案是合适的(尽管,这基本上是他的答案)。

RequireJS uses "paths" to find libs that aren't "AMD" supported and loads them on your page. RequireJS使用“路径”来查找不支持“AMD”的库,并将其加载到页面上。 the "shim" object allows you to define dependencies for the libraries defined in paths. “shim”对象允许您为路径中定义的库定义依赖项。 The dependencies must be loaded before requirejs will try to load the dependent script. 必须在requirejs尝试加载依赖脚本之前加载依赖项。

The exports property provides a mechanism to tell requirejs how to determine if the library is loaded. exports属性提供了一种机制来告诉requirejs如何确定是否加载了库。 For core libs like jquery, backbone, socketio, etc they all export some window level variable ( Backbone , io , jQuery and $ , etc). 对于像jquery,backbone,socketio等核心库,它们都会导出一些窗口级变量( BackboneiojQuery$等)。 You simply provide that variable name as the exports property, and requirejs will be able to determine when the lib is loaded. 您只需将该变量名称作为exports属性提供,并且requirejs将能够确定何时加载lib。

Once your definitions are done, you can use requirejs ' define function as expected. 完成定义后,可以按预期使用requirejsdefine函数。

Here's my example require.config object: 这是我的示例require.config对象:

require.config({
    baseUrl: "/js/",

    paths: {
        jquery: 'jquery',
        socketio: 'http://localhost:8000/socket.io/socket.io', //for loading the socket.io client library
        highcharts: 'libs/highcharts/highcharts.src',
        underscore: 'libs/underscore',
        backbone: 'libs/backbone'
    },

    shim: {
        jquery: {
            exports: 'jQuery'
        },

        socketio: {
            exports: 'io'
        },

        underscore: {
            exports: '_'
        },

        backbone: {
            deps: ['jquery', 'underscore'],
            exports: 'Backbone'
        },

        highcharts: {
            deps: ['jquery'],
            exports: 'Highcharts'
        }
    }
});

As pabera mentioned before, this is for Require.JS version 2.0.1 . 正如前面提到的pabera ,这是针对Require.JS版本2.0.1

I hope someone gets some use out of this; 我希望有人能从中得到一些用处; I know it road blocked me for a little while; 我知道这条路阻挡了我一会儿; so hopefully we kept you from banging your head into the same spot in the wall that we did, by posting this. 所以希望我们通过发布这个来阻止你把我的头撞到我们所做的墙上的同一个地方。

I had the exact same problem and I was struggling around many hours until I saw your entry here. 我有完全相同的问题,我在很长时间内挣扎,直到我看到你进入这里。 Then I started over from scratch and now it works for me at least. 然后我从头开始,现在它至少对我有用。

requirejs.config({
    baseUrl:'/js/',
    paths:{
      jquery:'vendor/jquery',
      handlebars: 'vendor/handlebars',
      text: 'vendor/require-text',
      chaplin:'vendor/chaplin',
      underscore:'vendor/underscore',
      backbone:'vendor/backbone',
      highcharts: 'vendor/highcharts'
    },

    shim: {
      backbone: {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      },
      underscore: {
        exports: '_'
      },    
      highcharts: {
        exports: 'Highcharts'
      }    
    },
});

Since I use Chaplin on top of Backbone, I am including some more files in my paths attribute. 由于我在Backbone之上使用Chaplin ,因此我在路径属性中包含了更多文件。 Highcharts has a similar structure to Backbone so I thought I could load it the same way. Highcharts与Backbone有类似的结构,所以我想我可以用同样的方式加载它。 It works for me now. 它现在对我有用。 As you can see, I am introducing highcharts in the paths attribute already to export it as a shim afterwords. 正如您所看到的,我在paths属性中引入了highcharts,将其导出为shim afterwords。

Maybe this helps, otherwise let's try to contribute on it even more to solve your problem. 也许这会有所帮助,否则我们会尝试为此做出更多贡献来解决您的问题。

Although jQuery can be used as an AMD module it will still export itself to the window anyway so any scripts depending on the global jQuery or $ will still work as long as jQuery has loaded first. 虽然jQuery可以用作AMD模块,但它仍然会将自己导出到窗口,因此任何依赖于全局jQuery$脚本在jQuery首先加载时仍然可以工作。

Have you tried setting a path? 你尝试过设置路径吗? jQuery is an interesting one because although you're encoruaged not to name your modules by the RequireJS documentation, jQuery actually does. jQuery是一个有趣的例子,因为尽管你不是通过RequireJS文档命名你的模块,但jQuery确实如此。

From the jQuery source 来自jQuery源码

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
    define( "jquery", [], function () { return jQuery; } );
}

What that means is you will need to tell RequireJS where to find 'jquery'. 这意味着你需要告诉RequireJS在哪里找到'jquery'。 So: 所以:

require.config({
    paths: {
        'jquery': 'path/to/jquery'
    }
});

If you're interested in why jQuery registers itself this way then there is a pretty large comment in the source which goes into more detail 如果你对jQuery为什么以这种方式注册自己感兴趣,那么源代码中有一个非常大的注释,它会更详细

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

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