我正在开发一个项目,该项目在具有有限资源的小型设备中的嵌入式Web浏览器中运行。浏览器本身有点过时,其功能有限(HTML 4.01†,W3C DOM Level 2†,JavaScript 1.4)。我没有关于浏览器的文档,所以我所知道的是来自反复试验。
重点是从服务器检索动态内容,以便只需要将少量不灵活的代码嵌入到运行Web浏览器的设备中。浏览器不支持XMLHTTPRequest对象,因此AJAX已经出局。与我合作,我写了一些测试代码来动态插入JavaScript。
†不支持这些标准的一小部分
修改 虽然我无法确认它,但我相信this site可能会列出对嵌入式浏览器的DOM支持,因为我看到“Mozilla / 4.0(兼容; EBSWebC 2.6; Windows NT 5.1)”作为服务器日志中的用户代理
<html>
<head>
</head>
<body onload="init()">
<div id="root"></div>
<script type="text/javascript">
<!--
function init() {
// Add a div element to the page.
var div = document.createElement("div");
div.id = "testDiv";
document.getElementById("root").appendChild(div);
// Set a timeout to insert the JavaScript after 2 seconds.
setTimeout("dynamicJS()", 2000);
}
function dynamicJS() {
...
}
//-->
</script>
</body>
</html>
我最初使用方法1 实现了dynamicJS
功能,并发现虽然代码在Chrome,IE8和FireFox 3.5中按预期执行,但嵌入式实际上并未检索到JavaScript附加元素时的浏览器。
function dynamicJS() {
var js = document.createElement("script");
js.type = "text/javascript";
js.src = "js/test.js";
document.getElementById("root").appendChild(js);
}
寻找解决方法,我实施了方法2 。这个方法实际上可以在嵌入式浏览器中工作,因为JavaScript被检索和执行,但它在我测试的其他现代网络浏览器中不起作用(Chrome,IE8,FireFox 3.5)。
function dynamicJS() {
var js= '<script type="text/javascript" src="js/test.js"> </s' + 'cript>';
document.getElementById("testDiv").innerHTML = js;
}
我是JavaScript和网络编程的新手,所以我希望这里的一位(或更多)专家可以为我阐明这一点。
方法2 是否存在技术上的错误,如果没有,为什么它不适用于现代网络浏览器?
答案 0 :(得分:3)
方法2没有任何技术上的错误,但大多数现代浏览器都有非常松散的HTML解析器,这些解析器往往会陷入您发送的代码中。具体来说,他们将JavaScript字符串文字中的</script>
解析为结束标记。这表现在两个方面:
</script>
文字后的所有代码都将在网页上呈现为文字。此问题的常见解决方法是拆分</script>
。您可以使用以下代码执行此操作。是的,我知道它是一个黑客,但它解决了这个问题。
function dynamicJS() {
var js= '<script type="text/javascript" src="js/test.js"></s' + 'cript>';
document.getElementById("testDiv").innerHTML = js;
}
但实际上,您应该能够严格使用DOM API来使用您的第一种方法。我发现有些浏览器在加载脚本添加的脚本方面非常挑剔,只有当它们作为<head>
元素的子元素放置时才会加载它们。这就是YUILoader的工作原理,所以如果它在所有浏览器中都不起作用,我会感到惊讶。
以下是一个示例,您需要检查这一点,以确保它适用于所有浏览器,并添加一些错误检查,假设会有一个<head>
元素,但它会给您一般的想法
if (!document.getElementsByTagName) {
document.getElementsByTagName = function(name) {
var nodes = [];
var queue = [document.documentElement];
while (queue.length > 0) {
var node = queue.shift();
if (node.tagName && node.tagName.toLowerCase() === name) {
nodes.push(node);
}
if (node.childNodes && node.childNodes.length > 0) {
for (var i=0; i<node.childNodes.length; i++) {
if (node.childNodes[i].nodeType === 1 /* element */) {
queue.push(node.childNodes[i]);
}
}
}
}
return nodes;
};
}
function dynamicJS() {
var js = document.createElement("script");
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', 'js/test.js');
var head = document.getElementsByTagName('head')[0];
head.appendChild(js);
}
答案 1 :(得分:2)
虽然所有现代浏览器都支持innerHTML
属性,但a definition of how it should work
属性尚未标准化,HTML5草案标准包括HTML5 specification。根据{{3}}:
使用
document.write()
方法插入时,script
元素执行(通常是同步),但使用innerHTML
和innerHTML
属性插入时,它们根本不会执行。
innerHTML
最初是在Microsoft Internet Explorer 4中引入的,由于其在作者中的流行,已被所有其他浏览器采用,这导致其被包含在HTML5中。所以,让我们检查outerHTML:
使用 innerHTML 插入脚本时,必须在Microsoft's documentation元素中包含DEFER属性。
显然,在IE中你可以通过defer
插入脚本来执行,但只有你添加defer
属性(我没有在我面前测试IE)。 <script defer>
是另一个首次添加到IE的功能;它是script,但很长一段时间没有被任何其他浏览器选中。 included in HTML 4.01包含有关innerHTML
应如何工作的更详细说明,但它似乎与IE中的工作原理略有不兼容,因为它不允许执行通过<script defer>
添加的脚本。 HTML innerHTML
HTML5的定义。
总之,defer
尚未真正标准化,而是由所有浏览器供应商以略微不同的方式实现。在原始实现的IE中,除了defer
属性之外,它不支持脚本的执行,并且直到最近才在其他浏览器中支持innerHTML
,因此其他浏览器只是不支持执行使用innerHTML
添加的脚本。这种行为是HTML5标准化的行为,因此除非Microsoft对象可能会成为标准的内容。
听起来你正在使用的浏览器并没有像实现兼容的innerHTML
一样好,因为它执行使用{{1}}添加的脚本,无论如何。这并不令人惊讶,因为行为不是标准化的,因此需要进行逆向工程或从阅读其他浏览器的文档中收集(过去可能没有包含此事实)。 HTML5的主要目标之一是实际记下所有这些未写入的假设和未记录的行为,以便将来实施浏览器的人可以这样做,而不会被与现实不匹配的规范误导,或者没有努力对现有浏览器进行逆向工程。
我认为您可能必须在嵌入式浏览器上使用方法2 ,如果要在常用桌面浏览器上运行,则方法1 。首先尝试方法1 可能是一个好主意,如果不起作用,则回退到方法2 ,然后出错(或者默默地失败,取决于如果两者都不起作用,你的需要。
答案 2 :(得分:0)
远景但嵌入式浏览器是否支持iframe? 如果是这样,您是否可以使用它来加载您需要的任何其他JS并通过iframe访问它?