8

以下代码 [ jsfiddle ] ...

var div = document.createElement("div");
div.innerHTML = "<foo>This is a <bar /> test. <br> Another test.</foo>";
alert(div.innerHTML);

...显示了这个解析的结构:

<foo>This is a <bar> test. <br> Another test.</bar></foo>

即浏览器知道<br>没有结束标签,但由于<bar>浏览器是未知标签,它假定它需要一个结束标签。

我知道/>(solidus)语法在 HTML5 中被忽略并且在 HTML4 中无效,但无论如何我想以某种方式教<bar>不需要结束标记的浏览器,我可以省略它。那可能吗?

是的,我正在尝试(暂时)滥用自定义标签的 HTML 代码,我有特定的理由这样做。毕竟,浏览器应该忽略未知标签并将它们视为无样式的内联标签,所以我不应该破坏任何东西,只要我能确保标签名称永远不会在真正的 HTML 标准中使用。

4

1 回答 1

7

您必须在 HTMLElement.prototype 上使用Object.defineProperty来使用您自己的 innerHTML 实现覆盖 innerHTML setter 和 getter,该实现将您想要的元素视为void在此处查看默认情况下如何实现 innerHTML 和 HTML 解析器。

请注意,尽管 Firefox 在定义 HTMLElement.prototype 上的内容时很糟糕,例如过滤到 HTMLDivElement 。不过,在 Opera 中应该可以正常工作。

换句话说,什么元素是无效的取决于 HTML 解析器。解析器遵循这个列表,innerHTML 大多使用相同的规则。

因此,换句话说,除非您想在 JS 中创建自己的 innerHTML 实现,否则您可能应该忘记这一点。

您可以使用实时 DOM 查看器向其他人展示如何解析某些标记。然后您可能会注意到相同的结束标记将隐式关闭打开的元素。

这里有一些过时的 innerHTML getter(虽然不是 setter)代码,它使用了一个 void 元素列表。这可能会给你一些想法。但是,编写一个 setter 实现可能会更加困难。

另一方面,如果您使用 createElement() 和 appendChild() 等代替 innerHTML,您不必担心这一点,并且本机 innerHTML getter 将输出带有结束标记的未知元素。

但请注意,您可以将未知元素视为 xml 并使用 XMLSerializer() 和 DOMParser() 来执行操作:

var x = document.createElement("test");
var serializer = new XMLSerializer();
alert(serializer.serializeToString(x));
var parser = new DOMParser();
var doc = parser.parseFromString("<test/>", "application/xml");
var div = document.createElement("div");
div.appendChild(document.importNode(doc.documentElement, true));
alert(serializer.serializeToString(div));

这不是你想要的,而是你可以玩的东西。(在 Opera 而不是 Firefox 中测试以查看与 xmlns 属性的区别。还要注意 Chrome 不像 Opera 和 Firefox。)

于 2012-02-01T10:48:23.020 回答