假设您有一个简单的网页,可以动态加载如下所示的内容:
- main.html -
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.2.js">
</script>
<script type="text/javascript">
$(function() {
$.ajax({
type: 'get', cache: false, url: '/svc.html',
success: function(h) {
$('#main').html(h);
}
});
});
</script>
</head>
<body>
<div id='main'>
loading...
</div>
</body>
</html>
并且它加载的页面在单独的文件中使用了一点Javascript:
- svc.html -
<script type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.2.js">
</script>
<script type="text/javascript" src="/plugin.js" css="/plugin.css"></script>
<div id='inner'>
dynamically loaded content
</div>
注意脚本标记上的css
属性 - 它表示属于脚本的样式表以及脚本将为我们加载的样式表。这是脚本:
- plugin.js -
var css = $('<link />', {
rel: "stylesheet", type: "text/css", href: $('script:last').attr('css')
});
$('head').append(css);
,最后,样式表只是为加载的inner
div着色,证明它一切正常:
- plugin.css -
#inner
{
border: solid 1px blue;
}
现在,您会注意到样式表的加载方式:我们查看$('script')
并选择最后一个,然后我们获取css
属性并附加{{1} } item到文档的头部。
我可以访问link
并运行javascript,加载我的样式表,一切都很酷 - 但是,如果我访问/svc.html
,javascript会运行但无法找到{{1}的加载在/main.html
的数组中(因此无法加载样式表)。请注意,插件脚本确实运行,它只是看不到自己。
这是一个错误吗? jQuery AJAX方法的局限性?不应该plugin.js
反映已加载的所有脚本吗?
*编辑*
经过多次哀号和咬牙切齿之后,我决定选择Kevin B的解决方案,但是,我无法让它工作,主要是因为$('script')
代码在$('script')
时运行插入,但在插件代码中,节点尚未插入,因此在plugin.js
数组中不可用 - 所以我仍然是SOL。我已将所有代码放在此处进行审核:
答案 0 :(得分:5)
向DOM添加HTML的jQuery代码总是删除<script>
标记。它运行它们然后将它们扔掉。
该行为的一个例外是当你使用“$ .load()”和hack时,你可以加载一个页面片段:
$.load("http://something.com/whatever #stuff_I_want", function() { ... });
在这种情况下,脚本将被剥离并且不评估/运行。
答案 1 :(得分:1)
你可以使用$ .ajax来获取html,自己去掉脚本标签,附加内容,然后将脚本标签附加到你想要它的dom中的位置,以便它以你想要的方式执行到。
$.ajax({...}).done(function(html){
var htmlToAppend = html;
// replace all script tags with divs
htmlToAppend.replace(/<script/ig,"<div class='script'");
htmlToAppend.replace(/<\/script>/ig,"</div>");
// detach script divs from html
htmlToAppend = $(htmlToAppend);
var scripts = htmlToAppend.find(".script").detach();
// append html to target div
htmlToAppend.appendTo("#target");
// loop through scripts and append them to the dom
scripts.each(function(){
var $script = $(this),
scriptText = $script.html(),
scriptNode = document.createElement('script');
$(scriptNode).attr('css', $script.attr('css');
scriptNode.appendChild(document.createTextNode(scriptText));
$("#target")[0].appendChild(scriptNode);
});
});
我没有测试过这段代码,但它是基于history.js的代码
编辑:这是一个更适合您需求的简单解决方案:
$("#target").load(url,function(obj){
// get css attribute from script tag using the raw returned html
var cssPath = obj.responseText.match(/css="(.*)"/i)[1];
$('<link />', {
rel: "stylesheet", type: "text/css", href: cssPath
}).appendTo('head');
});
因为.load()剥离脚本标记然后执行它们,这将读取原始响应文本并从中获取css路径,然后添加链接元素。
我不完全确定为什么会这样处理。
编辑:见评论。
$.ajax({...}).done(function(html){
$("#target")[0].innerHTML = html;
});
答案 2 :(得分:1)
我的解决方案很简单
为什么不在第一次加载时加载main中所需的文件?然后简单地有一个监听器事件。 (检查内容是否只是加载?)
按需加载的唯一解决方案......
你只需要AJAX调用脚本文件本身......
<script type="text/javascript">
$(function () {
$.ajax({
type: 'get',
cache: false,
url: 'svc.html',
success: function(response) {
if (response) { // If any response aka, loaded the svc.html file...
$('#main').html(response);
$.ajax({
url: 'plugin.js',
dataType: 'script',
success: function(reponse) {
// You can now do something with the response here even...
}
});
}
}
});
});
</script>
我的方式
在显示任何内容之前,在加载的实际页面上制作某种类型的加载程序。 (很多关于网络的jQuery教程。)
答案 3 :(得分:0)
这里的问题是你无法在每个页面重新加载jQuery。只是主页 应该有jQuery调用:
<script type='text/javascript' src='jQuery-url'></script>
或者只有一个页面可以调用它,只有孩子(是的,页面。从那里加载)将能够使用jQuery。
在我吸取教训之前,我曾经遇到过几次。这可能不是您问题的完整答案,但可能是解决问题的开始。
答案 4 :(得分:0)
- loadWithJs.js -
// inspired by Kevin B's suggestions
// at: http://stackoverflow.com/questions/8234215/where-are-scripts-loaded-after-an-ajax-call
(function ($) {
$.fn.loadWithJs = function (o) {
var target = this;
var success = o.success;
o.success = function (html) {
// convert script tags
html = $('<div />').append(
html.replace(/<(\/)?script/ig, "<$1codex")
);
// detach script divs from html
var scripts = html.find("codex").detach();
// populate target
target.html(html.children());
// loop through scripts and append them to the dom
scripts.each(function () {
var script = $(this)[0];
var scriptNode = document.createElement('script');
for (var i = 0; i < script.attributes.length; i++) {
var attr = script.attributes[i];
$(scriptNode).attr(attr.name, attr.value);
}
scriptNode.appendChild(
document.createTextNode($(script).html())
);
target[0].appendChild(scriptNode);
});
if (success) success();
};
$.ajax(o);
};
})(jQuery);
然后调用者可以这样做:
$(function() {
$('#main').loadWithJs({
type: 'get', cache: false,
url: '/svc.html',
success: function() { console.log('loaded'); }
});
});