Javascript 什么';s Require.js与简单创建<;脚本>;DOM中的元素?
使用Require.JS和简单地在DOM中创建Javascript 什么';s Require.js与简单创建<;脚本>;DOM中的元素?,javascript,requirejs,dynamic-script-loading,js-amd,Javascript,Requirejs,Dynamic Script Loading,Js Amd,使用Require.JS和简单地在DOM中创建元素有什么区别 我对Require.JS的理解是,它提供了加载依赖项的能力,但这不能简单地通过创建一个加载必要的外部JS文件的元素来实现吗 例如,假设我有函数doStuff(),它需要函数needMe()doStuff()在外部文件do_stuff.js中,而needMe()在外部文件need_me.js中 以Require.JS的方式执行此操作: define(['need_me'],function(){ function doStuff
元素有什么区别
我对Require.JS的理解是,它提供了加载依赖项的能力,但这不能简单地通过创建一个加载必要的外部JS文件的
元素来实现吗
例如,假设我有函数doStuff()
,它需要函数needMe()
doStuff()
在外部文件do_stuff.js
中,而needMe()
在外部文件need_me.js
中
以Require.JS的方式执行此操作:
define(['need_me'],function(){
function doStuff(){
//do some stuff
needMe();
//do some more stuff
}
});
function doStuff(){
var scriptElement = document.createElement('script');
scriptElement.src = 'need_me.js';
scriptElement.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
//do some stuff
needMe();
//do some more stuff
}
只需创建一个脚本元素即可执行此操作:
define(['need_me'],function(){
function doStuff(){
//do some stuff
needMe();
//do some more stuff
}
});
function doStuff(){
var scriptElement = document.createElement('script');
scriptElement.src = 'need_me.js';
scriptElement.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
//do some stuff
needMe();
//do some more stuff
}
这两种方法都有效。但是,第二个版本并不要求我加载所有require.js库。我真的看不到任何功能上的差异…这是ajaxian.com上关于为什么要使用它的好文章:
- 某种#包括/导入/要求
- 加载嵌套依赖项的能力
- 易于开发人员使用,但有助于部署的优化工具支持
needMe()
函数将在need_me.js文件完成加载之前被调用。这会导致未定义函数的未捕获异常
相反,要使您的建议真正起作用,您需要做如下操作:
function doStuff(){
var scriptElement = document.createElement('script');
scriptElement.src = 'need_me.js';
scriptElement.type = 'text/javascript';
scriptElement.addEventListener("load",
function() {
console.log("script loaded - now it's safe to use it!");
// do some stuff
needMe();
//do some more stuff
}, false);
document.getElementsByTagName('head')[0].appendChild(scriptElement);
}
可以说,使用诸如RequireJS之类的包管理器或使用上面演示的纯JavaScript策略可能是最好的,也可能不是最好的。虽然Web应用程序的加载速度可能更快,但调用站点上的功能和特性的速度会更慢,因为这将需要等待资源加载,然后才能执行该操作
如果Web应用程序是作为单页应用程序构建的,那么考虑到人们实际上不会频繁地重新加载页面。在这些情况下,预加载所有内容将有助于在实际使用应用程序时让体验看起来更快。在这些情况下,您是对的,只需在页面的头部或正文中包含脚本标记,就可以加载所有资源
但是,如果按照更传统的模式构建网站或Web应用程序,即从一个页面转换到另一个页面,导致资源被重新加载,那么延迟加载方法可能有助于加快这些转换。使用RequireJS有意义的其他一些非常明确的原因:
抽象层可能是一个需要学习和适应的噩梦,但当它达到目的并且做得很好时,它才有意义。这里有一个更具体的例子 我在一个有60个文件的项目中工作。我们有两种不同的运行模式
<script src="loader.js"></script>
构建脚本只是一个.sh文件,如下所示
if (useDebugVersion) {
injectScript("app.js");
injectScript("somelib.js");
injectScript("someotherlib.js");
injectScript("anotherlib.js");
... repeat for 60 files ...
} else {
injectScript("large-concatinated.js");
}
cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
injectScript("lib1.js");
injectScript("lib2.js");
等等
如果添加了一个新文件,我们可能会使用模式2,因为我们正在进行开发,我们必须向loader.js添加一个injectScript(“somenewfile.js”)
行
然后在以后的生产中,我们还必须向构建脚本添加一些newfile.js。这是我们经常忘记的步骤,然后会收到错误消息
通过切换到AMD,我们不必编辑2个文件。保持loader.js和构建脚本同步的问题消失了。使用r.js
或webpack
只需读取代码即可构建large concentated.js
它还可以处理依赖关系,例如,我们有两个文件lib1.js和lib2.js像这样加载
if (useDebugVersion) {
injectScript("app.js");
injectScript("somelib.js");
injectScript("someotherlib.js");
injectScript("anotherlib.js");
... repeat for 60 files ...
} else {
injectScript("large-concatinated.js");
}
cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
injectScript("lib1.js");
injectScript("lib2.js");
lib2需要lib1。它的内部有代码,类似于
lib1Api.installPlugin(...);
但是,由于注入的脚本是异步加载的,因此不能保证它们将以正确的顺序加载。这两个脚本不是AMD脚本,但使用require.js我们可以告诉它它们的依赖关系
require.config({
paths: {
lib1: './path/to/lib1',
lib2: './path/to/lib2',
},
shim: {
lib1: {
"exports": 'lib1Api',
},
lib2: {
"deps": ["lib1"],
},
}
});
我们的模块使用lib1,我们这样做
define(['lib1'], function(lib1Api) {
lib1Api.doSomething(...);
});
现在require.js将为我们注入脚本,在加载lib1之前它不会注入lib2,因为我们告诉它lib2依赖于lib1。在lib2和lib1都加载之前,它也不会启动使用lib1的模块
这使开发变得很好(无需构建步骤,无需担心加载顺序),并使生产变得很好(无需为添加的每个脚本更新构建脚本)
作为一个额外的好处,我们可以使用webpack的babel插件在旧浏览器的代码上运行babel,同样,我们也不必维护构建脚本
请注意,如果Chrome(我们选择的浏览器)开始真正支持import
,我们可能会转而使用它进行开发,但这不会真正改变任何事情。我们仍然可以使用webpack生成一个连接文件,并且可以使用它在所有浏览器的代码上运行babel
所有这些都是通过不使用脚本标记和使用AMD获得的,我已经读过这些,但是现在我想得更多了,我意识到嵌套依赖的想法不能通过简单地编写标记来实现。谢谢,“开发人员的易用性”与事实相差甚远。它肯定有一个陡峭的学习曲线,你和任何其他人谁会来工作,在这个项目。@ TwitelPyPoi我认为自己并不光明,要求JJ并不真的是一件很难的事情,我得到。这样你就不用担心depen了