使用Require.JS和<script>在DOM中创建元素之间的区别是什么?
我对Require.JS的理解是它提供了加载依赖项的能力,但这不能简单地通过创建一个<script>加载必要的外部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
}
});
Run Code Online (Sandbox Code Playgroud)
只需创建一个脚本元素即可:
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
}
Run Code Online (Sandbox Code Playgroud)
这两项都有效.但是,第二个版本不要求我加载所有Require.js库.我真的没有看到任何功能差异......
我使用yepnope.js动态加载javascript文件,我注意到我的脚本似乎根据Firebug和Webkit Inspector加载了两次.
问题是在Firebug的Net面板(Firefox 4最新版)中,他们的反应是200,而不是304.它似乎比Chrome慢.
我上传了这个显示问题的视频.您可以看到文件jquery-1.6.1.min.js和libs.js加载的时间.
我用来执行此操作的代码如下,简化:
Modernizr.load({
load: ['jquery-1.6.1.min.js', 'libs.js'],
complete: function () {
console.log("loaded");
}
});
Run Code Online (Sandbox Code Playgroud)
Modernizr.load()是yepnope().
我只是试图包装我们的一个模块,这些模块通过<script>一些样板中的标签包含在内,以允许可选的AMD加载requirejs.
这是非常痛苦的,我能想到的最好的是:
(function(){
var exports, jQuery;
if (typeof window.define === 'function' && typeof window.requirejs === 'function') {
exports = {};
define(['jquery'], function (jq) {
jQuery = jq;
return thisModule();
});
} else {
exports = window;
jQuery = window.jQuery;
thisModule();
}
function thisModule() {
}
})();
Run Code Online (Sandbox Code Playgroud)
请注意,这是
我主要关心的是第二点,因为当我超越包装我们的核心文件时,它将会变得很糟糕.我确定那里有一些整洁的(呃)包装器实现,但我找不到任何.
有人有任何提示吗?
在加载时,在Underscore上执行代码的正确方法是什么?我正在尝试执行以下代码,以便在模块需要时自动扩展_ exported namespace:
_.mixin(_.str.exports());
Run Code Online (Sandbox Code Playgroud)
文档有点模糊,但我想我把它放在shim init部分?我试过以下但是我甚至无法在init中获得一个断点:
require.config({
paths: {
jquery: 'libs/jquery/jquery.min',
underscore: 'libs/underscore/lodash.min',
underscorestring: 'libs/underscore/underscore.string.min'
},
shim: {
underscore: {
exports: '_'
}
underscorestring: {
deps: ['underscore'],
init: function (_) {
//Mixin plugin to namespace
_.mixin(_.str.exports());
return _;
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
当我尝试这样做并使用underscorestring时,我收到此错误:
未捕获的TypeError:对象函数s(e){return new o(e)}没有方法'startsWith'
文档:
javascript asynchronous dynamic-script-loading requirejs underscore.js
您将如何动态加载Web组件 - 例如,响应URL路由更改?
我不会提前知道所请求的组件,所以你可以简单地使用JavaScript来编写HTML导入,然后将代码添加到页面中,或者是否有这样的含义?Google Polymer可能有帮助吗?
javascript html5 web-component dynamic-script-loading polymer
我在Ajax中加载HTML,解析它DOMParser并将所有childNodes文档主体放入文档片段中.
当我将片段添加到当前文档的正文中时,<script>不会执行标记.
我摆弄并想出如果我用新动态创建的脚本标签替换它们,它们就会被正确执行.
我想知道为什么?
例如
var html = "Some html with a script <script>alert('test');</script>";
var frag = parsePartialHtml(html);
fixScriptsSoTheyAreExecuted(frag);
document.body.appendChild(frag);
function fixScriptsSoTheyAreExecuted(el) {
var scripts = el.querySelectorAll('script'),
script, fixedScript, i, len;
for (i = 0, len = scripts.length; i < len; i++) {
script = scripts[i];
fixedScript = document.createElement('script');
fixedScript.type = script.type;
if (script.innerHTML) fixedScript.innerHTML = script.innerHTML;
else fixedScript.src = script.src;
fixedScript.async = false;
script.parentNode.replaceChild(fixedScript, script);
}
}
function parsePartialHtml(html) {
var doc = …Run Code Online (Sandbox Code Playgroud) 我是Browserify的新手,我正在努力弄清楚如何使客户端需要下载的效率更高.
我有一个Web应用程序,它使用许多不同的第三方库和自定义代码.使用Browserify,似乎人们建议将一切都包装成一个大的一般方法bundle.js.由于以下几个原因,这对我来说似乎非常低效:
例如,让我们说你的bundle.js包含lib1, lib2, lib3, customLib.
lib1客户端仍然必须下载巨大的bundle.js,它最终不使用75%的.已下载浪费的字节.不必要地增加了页面加载时间.customLib是经常迭代的代码,那么每次更改时,您的客户都必须重新下载bundle.js,再次下载大量未更改的第三方库...您的网络应用程序的其他部分可能会使用lib2,lib3但客户端可能会或可能不会去那里,他绝对浪费带宽下载整个bundle.js.
我已经看到了将捆绑包分成多个捆绑包的建议.但到底是什么?如果一个页面使用lib1,其他页面使用lib1,并lib2和另一个页面使用lib2和lib3,那么你如何分割它呢?你把它分成多个捆绑包的次数越多,你是不是会摆脱优势bundle.js?
Browserify似乎受到高度重视,所以我希望我在这里错过了一些东西.将许多库和自定义脚本捆绑在一起的正确方法是什么?人们将Browserify称为"脚本加载器",但我过去看过的每个脚本加载器(如yepnope等)都使用逻辑来确定要下载的脚本,这似乎是一个更有效的解决方案,而Browserify似乎希望客户端能够下载一切......
我<script>在页面加载后动态地向head元素添加了一些标签.我理解脚本是异步加载的,但是我可以期望它们按照添加的顺序进行解析吗?
我在Firefox中看到了预期的行为,但在Safari或Chrome中却没有.查看Chrome开发人员工具和Firebug中的文档,两者都显示以下内容 -
<html>
<head>
...
<script type="text/javascript" src="A.js"></script>
<script type="text/javascript" src="B.js"></script>
</head>
...
</html>
Run Code Online (Sandbox Code Playgroud)
但是,在查看资源加载视图时,chrome似乎会解析从服务器首先返回的任何一个,而firebug总是按照添加脚本标记的顺序加载它们,即使首先从服务器返回B也是如此.
我是否希望Chrome/Safari按指定顺序解析文件?在OS X 10.6.3上使用Chrome 5.0.375.29 beta
编辑(10/5/10):当我说解析时,我的意思是执行 - 可以看到积极解析的许多好处 - thx rikh
编辑(11/5/10):好的,所以我按照下面的juandopazo的说法进行了测试.但是我添加了一些东西,包括
我还尝试了脚本标签上"async"和"defer"属性的所有组合.
您可以在此处访问测试 - http://dyn-script-load.appspot.com/,并查看源代码以了解其工作原理.加载的脚本只需调用update()函数.
首先要注意的是,只有上述第一和第三种方法并行运行 - 第二种方法依次执行请求.你可以在这里看到这个图表 -
图1 - 请求生命周期
请求生命周期图表http://dyn-script-load.appspot.com/images/dynScriptGraph.png
有趣的是,jquery append()方法也阻止了getScript()调用 - 你可以看到它们都没有执行,直到所有append()调用完成,然后它们全部并行运行.关于这一点的最后一点是,jQuery append()方法在执行后显然会从文档头中删除脚本标记.只有第一种方法会在文档中保留脚本标记.
Chrome结果
结果是Chrome始终执行第一个要返回的脚本,无论测试如何.这意味着所有测试'失败',除了jQuery append()方法.
图2 - Chrome 5.0.375.29测试结果
Chrome结果http://dyn-script-load.appspot.com/images/chromeDynScript.png
Firefox结果
但是,在firefox上,如果使用第一个方法,并且async为false(即未设置),那么脚本将按顺序可靠地执行.
图3 - FF 3.6.3结果
FF结果http://dyn-script-load.appspot.com/images/ffDynScript.png
请注意,Safari似乎以与Chrome相同的方式提供不同的结果,这是有道理的.
此外,我在慢速脚本上只有500毫秒的延迟,只是为了保持开始 - >结束时间.您可能需要刷新几次才能看到Chrome和Safari在所有内容上都失败了.
在我看来,没有这样做的方法,我们没有利用并行检索数据的能力,并且我们没有理由不应该(如firefox所示).
我正在尝试从书签中加载JS文件.JS文件有这个包装模块的JS:
(function (root, factory) {
if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals
root.moduleGlobal = factory();
}
}(this, function factory() {
// module script is in here
return moduleGlobal;
}));
Run Code Online (Sandbox Code Playgroud)
因此,如果网页使用RequireJS,则脚本在加载时不会导出全局.为了解决这个问题我暂时设置define到null,加载脚本,然后重置define为其原始值:
function loadScript(url, cb) {
var s = document.createElement('script');
s.src = url;
s.defer = true; …Run Code Online (Sandbox Code Playgroud) javascript amd global-variables dynamic-script-loading requirejs
Spotify 在测试版中有一项新功能,支持在浏览器中播放完整歌曲,即 Web Playback SDK。该文档显示了使用主 HTML 文件中的脚本标签立即初始化播放器的示例。这需要立即在脚本中设置访问令牌。我的问题是我正在创建一个 React 应用程序,如果用户单击按钮登录到他们的 Spotify 帐户,我只想初始化一个播放器。为了仅在发生此事件时才加载脚本,我使用了 react-load-script。我想要的流程是:用户单击按钮登录他们的 Spotify 帐户,一旦他们的登录通过 Spotify 的身份验证,我的应用程序就会收到一个访问令牌,然后加载网络播放脚本,一旦加载脚本,就会调用回调函数并且播放器使用访问令牌进行初始化。
问题是Spotify对象直到加载了spotify-player脚本才存在。当实际调用handleScriptLoad回调时,定义了Spotify对象,但是在编译代码时却没有。有没有人有任何想法如何解决这个问题?
来自相关 React 组件的代码示例:
import Script from 'react-load-script'
...
handleScriptLoad = () => {
const token = this.props.tokens.access
const player = new Spotify.Player({ // Spotify is not defined until
name: 'Spotify Web Player', // the script is loaded in
getOAuthToken: cb => { cb(token) }
})
player.connect()
}
...
Run Code Online (Sandbox Code Playgroud)
在我的 React 组件的渲染方法中:
<Script
url="https://sdk.scdn.co/spotify-player.js"
onError={this.handleScriptError}
onLoad={this.handleScriptLoad}
/>
Run Code Online (Sandbox Code Playgroud) javascript ×10
requirejs ×3
amd ×2
asynchronous ×1
boilerplate ×1
browserify ×1
commonjs ×1
html ×1
html5 ×1
js-amd ×1
modernizr ×1
polymer ×1
reactjs ×1
spotify ×1
yepnope ×1