情况:
javascripts.js
部分中的一个文件<head>
与其他脚本一起动态加载jQuery(document).ready()
部分的<body>
上执行了自己的javascript代码问题:
<body>
部分中的javascript未定义 jQuery 示例html文件:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
jQuery(document).ready(function() { // Error: jQuery not defined
jQuery('.date').datepicker();
});
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
});
答案 0 :(得分:3)
正如评论中许多人所指出的那样,这种情况正在发生,因为你是异步加载jQuery的。异步意味着执行其余代码,因此在环境中存在jQuery之前,您的文档就绪处理程序(DRH)行正在运行。
这是真正 hacky解决这个问题的方法。它涉及到jQuery的临时替代,它的工作只是记录DRH回调,直到jQuery到达。当它发生时,我们依次将它们传递给jQuery。
<强> JS:强>
//temporary jQuery substitute - just log incoming DRH callbacks
function jQuery(func) {
if (func) drh_callbacks.push(func);
return {ready: function(func) { drh_callbacks.push(func); }};
};
var $ = jQuery, drh_callbacks = [];
//asynchronously load jQuery
setTimeout(function() {
var scr = document.createElement('script');
scr.src = '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js';
document.head.appendChild(scr);
scr.onload = function() {
$.each(drh_callbacks, function(i, func) { $(func); });
};
}, 2000);
<强> HTML:强>
jQuery(document).ready(function() { alert('jQuery has loaded!'); });
小提琴:http://jsfiddle.net/y7aE3/
请注意,在此示例中drh_callbacks
是全局的,这显然很糟糕。理想情况下将其挂在命名空间或其他东西上,例如mynamespace.drh_callbacks
。
答案 1 :(得分:1)
我相信这个简单的解决方案应该可以解决问题。 html中更改的行将jquery onload函数更改为常规函数。 jquery onload函数有时会在加载jquery之前发生,我们不能这样做。它不可靠。我们需要该函数不在页面加载时执行,但是在jquery加载之后。
为此,我在javascript.js中添加的三行都在jQuery加载完成后立即执行的代码中。他们测试是否已经定义了pageLoaded函数(所以你不必在每个页面上放置一个,只有需要它的那个),然后在那里执行它。
现在,因为对HTML的更改很简单,您只需进行正则表达式搜索并替换这1000个文件即可修复它们。 Sublime,Eclipse或TextPad等工具适用于该任务。
干杯!
示例html文件:
<html>
<head>
<title>JS test</title>
<script src="javascripts.js" type="text/javascript"></script>
</head>
<body>
<input type="text" class="date">
<script>
function pageLoaded() { // changed
jQuery('.date').datepicker();
} // changed
</script>
</body>
</html>
javascripts.js:
// Load jQuery before any other javascript file
function loadJS(src, callback) {
var s = document.createElement('script');
s.src = src;
s.async = true;
s.onreadystatechange = s.onload = function() {
var state = s.readyState;
console.log("state: "+state);
if (!callback.done && (!state || /loaded|complete/.test(state))) {
callback.done = true;
callback();
}
};
document.getElementsByTagName('head')[0].appendChild(s);
}
loadJS('javascripts/jquery-1.8.3.min.js', function() {
var files = Array(
'javascripts/functions.js',
'javascripts/settings.js'
);
if (document.getElementsByTagName && document.createElement) {
var head = document.getElementsByTagName('head')[0];
for (i = 0; i < files.length; i++) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', files[i]);
script.async = true;
head.appendChild(script);
}
}
if( typeof(pageLoaded) == "function" ){ // added
pageLoaded(); // added
} // added
});
答案 2 :(得分:0)
您应该尝试以下解决方法来同步加载脚本:
function loadJS(src, callback) {
document.write('<scr'+'ipt src="'+src+'"><\/scr'+'ipt>');
callback();
}
需要注意:在完全呈现DOM之前,应始终调用此函数。