Access global variables from Require.js in the Chr

2019-08-12 04:06发布

问题:

I am creating an ASP.NET single-page application, and have a require.js config file that runs on application start, referencing jQuery, Sammy.js, and knockout.js. I have created shims for the three third-party libraries to allow me to access them on a global level:

require.config({
    paths: {
        "jquery": "/Scripts/jquery-2.1.4.min",
        "sammy": "/Scripts/sammy-0.7.5.min",
        "knockout": "/Scripts/knockout-3.3.0",
        "text": "/Scripts/text",
        "appVm": "/Scripts/app/appViewModel"
    },
    shim: {
        "jquery": {
            exports: "$"
        },
        "sammy": {
            deps: ["jquery"],
            exports: "Sammy"
        },
        "knockout": {
            deps: ["jquery"],
            exports: "ko"
        }
    },
    priority: ["text", "app"],
});

define(["knockout", "appVm", "sammy"], function(ko, appVm, sammy) {
    var vm = new appVm();
    ko.applyBindings(vm);

    var app = sammy(function() {
        this.get("#Dashboard", function() {
            //Dashboard-related logic here
        });
    });
    app.run("#Dashboard");
});

I am able to instantiate my knockout viewmodel and bind it to the page. However, when I try to access the global variable "ko" for knockout to debug in the Chrome Developer console, nothing is defined.

How can I obtain the "ko" object for debugging in Chrome?

回答1:

You can expose the ko object as a global from your main function like this:

define(["knockout", "appVm", "sammy"], function(ko, appVm, sammy) {
    // expose ko as global
    window.ko = ko;

    var vm = new appVm();
    ko.applyBindings(vm);

    var app = sammy(function() {
        this.get("#Dashboard", function() {
            //Dashboard-related logic here
        });
    });
    app.run("#Dashboard");
});

Also you might want to check out the framework DurandalJS its a really nice framework that uses requirejs, KnockoutJS and JQuery. It has its own routing capabilities and a nice application lifecycle to work with.



回答2:

First, the configuration you pass to RequireJS is wrong.

priority is a RequireJS 1.x option, not recognized by RequireJS 2.x. shim is a RequireJS 2.x option, not recognized by RequireJS 1.x. Most likely you are running 2.x and priority does nothing.

Also, neither jQuery nor Knockout require shim configurations. If you use a shim with a module that does need it you get undefined behavior. Undefined behavior is just that "undefined". Maybe it works today, maybe it doesn't. Maybe it works today but 3 weeks from now when you add a new library to your project it does not work anymore.

As for getting a global reference to a module goes, you can do what Anish Patel recommended. It will work but I almost never do that. If I'm in the midst of debugging something and I must get a reference to a module, then:

  1. If the module I want was already loaded, then I take advantage of the pseudo-synchronous require that RequireJS offers for CommonJS compatibility and this at the console:

    foo = require('foo')
    
  2. Otherwise, I do:

    require(['foo'], function (foo_) { foo = foo_; });
    

    This is an asynchronous call but I've never had to actually wait for it to complete. You can always add a console.log statement after the assignment if you want to have visual indication that the assignment was done.

I prefer not to go into my code and add a statement to leak the module into the global space, which I may forget to remove later. Even if I were sure I would not forget, it means going into the code, rebuilding the application and reloading the page.