我编写了JavaScript库以使用FileSaver.js及其相关库。但是,每当有人想要使用我的库时,我都不想总是加载FileSaver.js。而且我不想强迫他们自己加载所有与script
标签相关的各种与FileSaver相关的JavaScript库(甚至加载我的一个也可以这样做)。
相反,我更喜欢的是这样的。当他们调用我的createImage
函数时,它首先执行以下操作:
function createImage(image, name) {
if (typeof(saveAs) !== 'function') {
var element = document.createElement('script');
element.async = false;
element.src = 'FileSaver.js';
element.type = 'text/javascript';
(document.getElementsByTagName('head')[0]||document.body).appendChild(element);
}
// now do the saveImage code
}
问题是,在上述之后,仍然没有定义saveAs
函数。只有 后我的createImage
完成才是最终定义的saveAs
函数。
答案 0 :(得分:9)
您可以定义模块之间的依赖关系,而require.js将在需要时获取它们。一般的想法是模仿其他语言(如java,C#或python)的导入/命名空间功能。 “代码共享”我认为这个词是什么?
只需将所有代码放在一个回调函数中,该函数在加载依赖项后运行,这样就可以确保所需的对象和方法存在。
更新2015
只是一个附录。虽然上面的信息仍然正确,但前端代码管理正在迅速向Webpack和Browserify等解决方案发展,它们捆绑和连接任何模块类型的代码,并且都具有动态代码加载功能(webpack调用此代码拆分)。加上依赖管理的npm指数增长,开始使AMD的相关性降低。
答案 1 :(得分:1)
好的,你需要做的就是听脚本完成加载。不幸的是,这个代码存在一些错误,即< 7。
这是Mootools Asset.javascript
加载脚本并在完成时调用回调的方式:
var loadScript = function (source, properties) {
properties || (properties = {});
var script = document.createElement('script');
script.async = true;
script.src = source;
script.type = 'text/javascript';
var doc = properties.document || document, load = properties.onload || properties.onLoad;
return delete properties.onload, delete properties.onLoad, delete properties.document,
load && (script.addEventListener ? script.addEventListener("load", load) : script.attachEvent("readystatechange", function() {
[ "loaded", "complete" ].indexOf(this.readyState) >= 0 && load.call(this);
})), script.set(properties).appendChild(doc.head);
}
现在在loadImage
中,您可以按如下方式加载文件库:
function createImage(image, name) {
function createImg() {
// now do the saveImage code
}
if (typeof(saveAs) !== 'function') {
loadScript("FileSaver.js", {onLoad: createImg});//load library
}
else {
createImg();
}
}
适用于大多数浏览器。
答案 2 :(得分:0)
使用Head.js:http://headjs.com/
它将按需加载脚本。
答案 3 :(得分:0)
所以我同意AMD的评论(不能将代码阻止到评论中......)
这是我为FileSaver.js做的事情
首先在我的requirejs config / main.js中:
(function() {
// REMEMBER TO DUPLICATE CHANGES IN GRUNTFILE.JS
requirejs.config({
paths: {
"jquery": "PATH/jquery.min", // NO .js
"lib.filesaver" : "PATH/FileSaver", // NO .js
"shim.blob" : "PATH/Blob" // NO .js
},
shim: {
"lib.filesaver": {deps: ["shim.blob"]}
}
});
define([
"jquery"
], function(
$
) {
$(document).ready(function() {
// start up code...
});
return {};
});
})();
然后我将Blob.js / jquery和Filersaver放在正确的位置
我还为IE10之前创建了一个IEShim
define([], function () {
/**
* @class IEshims
* container for static IE shim functions
*/
var IEShims = {
/**
* saveFile, pops up a built in javascript file as a download
* @param {String} filename, eg doc.csv
* @param {String} filecontent eg "this","is","csv"
*/
saveAs: function (filename, filecontent, mimetype ) {
var w = window.open();
var doc = w.document;
doc.open( mimetype,'replace');
doc.charset = "utf-8";
doc.write(filecontent);
doc.close();
doc.execCommand("SaveAs", null, filename);
}
};
return IEShims;
});
最后,当我想使用Filesaver时,需要它(对于糟糕的浏览器,还有IEShim)
define([
"lib.filesaver",
"IEShims"
],
function (
FileSaver, // it's empty, see saveAs global var
IEShims
) {
...
var fileName = "helloworld.txt";
var fileContents = "Me haz file contents, K Thx Bye";
var mimeType = "text/plain";
if(saveAs) {
var blob = new Blob(
[fileContents],
{type: mimeType + ";charset=" + document.characterSet}
);
saveAs(blob, fileName);
} else {
IEShims.saveAs(fileName, fileContents,mimeType );
}
...
};
答案 4 :(得分:0)
最简单的答案是将您的代码放在您创建的onload
标记的script
处理程序中:
<script>
var firstScript = document.getElementsByTagName('script')[0],
js = document.createElement('script');
js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
js.onload = function () {
// do stuff with your dynamically loaded script
snowStorm.snowColor = '#99ccff';
};
firstScript.parentNode.insertBefore(js, firstScript);
</script>
以这种方式动态加载脚本done by Facebook。