如何可靠地动态加载JavaScript文件?这将用于实现一个模块或组件,当'初始化'时,组件将根据需要动态加载所有需要的JavaScript库脚本.
使用该组件的客户端不需要加载实现此组件的所有库脚本文件(并手动将标记插入其网页) - 只需要"主"组件脚本文件.
主流JavaScript库如何实现这一目标(Prototype,jQuery等)? 这些工具是否将多个JavaScript文件合并为一个可再发行的"构建"版本的脚本文件?或者他们是否动态加载辅助"库"脚本?
这个问题的补充:有没有办法在加载动态包含的JavaScript文件后处理事件? 原型document.observe
适用于文档范围的事件.例:
document.observe("dom:loaded", function() { // initially hide all containers for tab content $$('div.tabcontent').invoke('hide'); });
脚本元素有哪些可用事件?
您可以编写动态脚本标记(使用Prototype):
new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});
这里的问题是我们不知道外部脚本文件何时完全加载.
我们经常希望我们的依赖代码在下一行,并喜欢写下这样的东西:
if (iNeedSomeMore) { Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod(); myFancyMethod(); // cool, no need for callbacks! }
有一种智能方法可以在不需要回调的情况下注入脚本依赖项.您只需通过同步AJAX请求拉出脚本并在全局级别上评估脚本.
如果使用Prototype,则Script.load方法如下所示:
var Script = { _loadedScripts: [], include: function(script) { // include script only once if (this._loadedScripts.include(script)) { return false; } // request file synchronous var code = new Ajax.Request(script, { asynchronous: false, method: "GET", evalJS: false, evalJSON: false }).transport.responseText; // eval code on global level if (Prototype.Browser.IE) { window.execScript(code); } else if (Prototype.Browser.WebKit) { $$("head").first().insert(Object.extend( new Element("script", { type: "text/javascript" }), { text: code } )); } else { window.eval(code); } // remember included script this._loadedScripts.push(script); } };
javascript中没有import/include/require,但有两种主要方法可以实现您的目标:
1 - 您可以使用AJAX调用加载它,然后使用eval.
这是最直接的方式,但由于Javascript安全设置,它仅限于您的域,并且使用eval可以打开错误和黑客的大门.
2 - 在HTML中添加带脚本URL的脚本标记.
绝对是最好的方式.您甚至可以从外部服务器加载脚本,并且在使用浏览器解析器评估代码时它是干净的.您可以将标记放在网页的头部或主体的底部.
这里讨论和说明了这两种解决方案.
现在,您必须了解一个大问题.这样做意味着您远程加载代码.现代Web浏览器将加载文件并继续执行当前脚本,因为它们异步加载所有内容以提高性能.
这意味着如果你直接使用这些技巧,在你要求加载后,你将无法在下一行使用新加载的代码,因为它仍然会加载.
EG:my_lovely_script.js包含MySuperObject
var js = document.createElement("script"); js.type = "text/javascript"; js.src = jsFilePath; document.body.appendChild(js); var s = new MySuperObject(); Error : MySuperObject is undefined
然后你重新加载页面击中F5.它的工作原理!混乱...
那该怎么办呢?
好吧,你可以在我给你的链接中使用作者建议的黑客.总之,对于匆忙的人,他在加载脚本时使用en事件来运行回调函数.因此,您可以使用远程库将所有代码放在回调函数中.EG:
function loadScript(url, callback) { // adding the script tag to the head as suggested before var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; // then bind the event to the callback function // there are several events for cross browser compatibility script.onreadystatechange = callback; script.onload = callback; // fire the loading head.appendChild(script); }
然后在lambda函数中加载脚本后编写要使用的代码:
var myPrettyCode = function() { // here, do what ever you want };
然后你运行所有:
loadScript("my_lovely_script.js", myPrettyCode);
好,我知道了.但写这些东西真是太痛苦了.
那么,在这种情况下,你可以像往常一样使用梦幻般的免费jQuery框架,它让你在一行中做同样的事情:
$.getScript("my_lovely_script.js", function() { alert("Script loaded and executed."); // here you can use anything you defined in the loaded script });
我最近用jQuery使用了一个不那么复杂的版本:
它在我测试的每个浏览器中都运行良好:IE6/7,Firefox,Safari,Opera.
更新: jQuery-less版本:
我做的基本上与你做亚当的事情相同,但稍加修改以确保我附加到head标签以完成工作.我只是创建了一个include函数(下面的代码)来处理脚本和css文件.
此函数还会检查以确保尚未动态加载脚本或CSS文件.它不检查手动编码值,并且可能有更好的方法来做到这一点,但它达到了目的.
function include( url, type ){ // First make sure it hasn't been loaded by something else. if( Array.contains( includedFile, url ) ) return; // Determine the MIME-type var jsExpr = new RegExp( "js$", "i" ); var cssExpr = new RegExp( "css$", "i" ); if( type == null ) if( jsExpr.test( url ) ) type = 'text/javascript'; else if( cssExpr.test( url ) ) type = 'text/css'; // Create the appropriate element. var tag = null; switch( type ){ case 'text/javascript' : tag = document.createElement( 'script' ); tag.type = type; tag.src = url; break; case 'text/css' : tag = document.createElement( 'link' ); tag.rel = 'stylesheet'; tag.type = type; tag.href = url; break; } // Insert it to the and the array to ensure it is not // loaded again. document.getElementsByTagName("head")[0].appendChild( tag ); Array.add( includedFile, url ); }
另一个很棒的答案
$.getScript("my_lovely_script.js", function(){ alert("Script loaded and executed."); // here you can use anything you defined in the loaded script });
/sf/ask/17360801/
以下是我发现的一些示例代码...有没有人有更好的方法?
function include(url) { var s = document.createElement("script"); s.setAttribute("type", "text/javascript"); s.setAttribute("src", url); var nodes = document.getElementsByTagName("*"); var node = nodes[nodes.length -1].parentNode; node.appendChild(s); }
如果你已经加载了jQuery,你应该使用$ .getScript.
这比其他答案有一个优势,因为你有一个内置的回调函数(以保证在依赖代码运行之前加载脚本),你可以控制缓存.