6

在我的应用程序中,有一些动态部分从数据库加载为字符串,如下所示:

"define(['dependency1', 'dependency2'], function(){"+
"   // function body" +
"})"

这只是一个简单的 requireJS 模块,作为一个字符串。我想使用 async require 调用延迟加载上面的脚本。所以,我的主要 requireJS 脚本看起来像:

require(["jquery"], function($){        
    $(document).ready(function(){
        // logic to load specific script from database
        var scriptString = functionToLoadTheStringAbove();

        // ideally i would like to call it like this            
        require([scriptString], function(){
           // scriptString, dependency1, dependency2 are loaded
        }
    });
});

如何在 requireJS 中加载这些字符串?我知道文本插件,但它只允许从文件加载。我尝试了 eval 但它没有正确解决依赖关系。

4

3 回答 3

6

这已经很晚了,但我只是在这里发布我的解决方案以防万一。

所以我最终在requireJS论坛上询问并检查了文本的来源!插件json!插件。在 RequireJS 中从 String 加载模块的最简洁方法是制作您自己的插件来加载 String,然后使用onLoad.fromText()来处理eval您的 String 并解析所有依赖项。

我的插件示例(我们称之为db!插件):

define([], function(){
    var db = new Database(); // string is loaded from LocalStorage
    return {
        load: function(name, req, onLoad, reqConfig){
            db.get(name, function(err, scriptString){
                if (err) onLoad(err);
                else onLoad.fromText(scriptString);
            });  
         }
    }
});

然后,您可以像这样使用插件:

require(["jquery", "db!myScript"], function($, myScript){        
    // jQuery, myScript and its dependencies are loaded from database
});

笔记:

  1. 没有. require()_ eval这就是onLoad.fromText()内部所做的。由于 eval 是邪恶的,因此只有在知道要使用什么 String 时才应该使用它eval()。如果您在浏览器扩展中使用它,您可能希望放宽 CSP 策略。
  2. 要命名您的 String 模块,您可以使用显式命名语法。这样,您的模块将始终具有相同的绝对名称。
于 2014-11-11T06:47:26.690 回答
0

要更直接地回答这个问题,请创建一个像这样的插件:

define("load-string",[], function(){
    var strings=[],
        re_package_name = /^string_module_(\d+)$/;
    return {
        normalize: function(name, _){
            if(re_package_name.test(name)){
                return name
            }
            var nml = "string_module_" + (strings.push(name)-1);
            return nml;
        },
        load: function(name, _, onLoad, config){
            if(re_package_name.test(name)){
                onLoad.fromText(strings[name.match(re_package_name)[1]]);
            }else{
                onLoad.error("Invalid package name: ",name);
            }
        }  
    }
});

并像这样使用它:

var world_module = "define([],function(){return 'world!'})";

require(["load-string!" + world_module],
    function(x){
        console.log("Hello "+x);
    })
于 2016-11-06T05:46:14.250 回答
-1

你应该能够做到:

require(["jquery"], function($){        
    $(document).ready(function(){
        // logic to load specific script from database
        var scriptString = functionToLoadTheStringAbove();

        var olddefine = define; // require js define 
        var runme; // capture function 
        define = function (args,func){
             runme = func; 
        }
        eval(scriptString);
        runme(); // run the function in current scope
        define = olddefine; // restore requirejs function 

        // dependency1, dependency2 are loaded        
    });
});
于 2013-04-26T04:35:31.383 回答