首先,很好的问题。
DOM Level 0-1 功能是我最喜欢使用的工具箱。支持是巨大的。我将在下面重点介绍每个 DOM 级别 0 子集的优缺点:
DOM 0 级事件
由于这些是作为 ElementNode 的属性添加的,因此您只能拥有一个处理程序。对于某些情况(例如:事件委托),这是繁重的。但是,我觉得 DOM 足够多样化(尤其是当您的项目变得更大时)可以为 DOM 0 级处理程序提供足够的空间。如果没有库/框架来平滑旧浏览器,则 DOM 2 级侦听器很难实现。即使作为 Flash 开发人员(到处都使用侦听器),DOM 0 事件对我来说也容易得多。其中一个亮点是this 值是为您设置的(没有像其他模型那样对 IE 进行黑客攻击和咳嗽)。例如,考虑这个标记:
<div id="foo">Cick Me!</div>
现在,需要做的就是选择和附加 DOM Level 0 处理程序。
var foo = document.getElementById("foo");
function bar()
{
console.log(this); //<div id="foo">
}
foo.onclick = bar;
这是选择元素的一种非常简单的方法,是Event.currentTarget 的替代方法;
这里有关于 DOM Level 0 事件与 DOM Level 2 事件的精彩讨论:[link]
DOM 级别 0 HTMLCollections
没有,HTMLCollections 是我最喜欢的 DOM 特性。因为为您选择了节点,所以无需运行查询。在我看来,它们是当今最被忽视的 DOM 特性。名称遍历,例如:collection["name"] 非常方便,在遍历表单时肯定会有所帮助。例如,考虑以下标记:
<form action="./" id="foo" name="foo" method="post" onsubmit="return false;">
<fieldset>
<legend>Dummy Form</legend>
<input type="text" name="bar">
<select name="baz">
<option selected value="1">1</option>
</select>
</fieldset>
</form>
有很多 DOM Level 0 方法可以解决这个问题。
-
var foo = document.forms.foo; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">
演示:http://jsbin.com/udozoz/0edit#preview
-
var foo = document.forms[0]; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">
演示:http://jsbin.com/udozoz/2/edit#preview
-
var foo = document.getElementById("foo"); //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">
演示:http://jsbin.com/udozoz/3/edit#preview
当然,方法3更优选。它是 DOM 级别 1,而不是 DOM 级别 0。但是,名称遍历自然适合 HTMLFormElement.elements HTMLCollection。由于您应该在表单元素上使用name 属性,因此无需id 属性即可轻松访问它们。
例如:var baz = foo.elements.baz;
当使用同名的单选按钮时(一次只能选择一个),您可以使用HTMLFormElement.elements HTMLCollection 来选择所有单选按钮。这是非常强大的。考虑这个标记:
<form action="./" id="foo" name="foo" method="post" onsubmit="return false;">
<fieldset>
<legend>Radio Buttons</legend>
<label for="select_1">1</label>
<input id="select_1" type="radio" name="selectable" value="a">
<label for="select_2">2</label>
<input id="select_2" type="radio" name="selectable" value="b">
<label for="select_3">3</label>
<input id="select_3" type="radio" name="selectable" value="c">
</fieldset>
</form>
您可以使用这个简单的代码,让每个单选按钮的name 属性值为“可选”:
-
var foo = document.forms.foo;
var selectables = foo.elements.selectable;
console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
演示:http://jsbin.com/upiyom/edit#preview
-
var foo = document.forms.foo;
var selectables = foo.selectable;
console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
演示:http://jsbin.com/upiyom/2/edit#preview
选项 2 使您能够完全绕过 elements HTMLCollection。虽然肯定不如选项 1 清晰,但它今天仍在使用。
HTMLCollections 自引入 DOM Level 0 以来变得越来越多,也越来越多样化。例如,看看可用于表格的 HTMLCollections。这是惊人的。有HTMLTableElement.rows、HTMLTableElement.tBodies、HTMLTableSectionElement (thead, tbody, tfoot).rows 和HTMLTableRowElement.cells。这些集合非常强大,并且使用表(允许您使用它们)使 DOM 遍历变得更加简单。
DOM 0 级属性
虽然 ElementNodes 上的属性在 DOM 级别 0 中不像现在那样多样化,但仍有一些亮点需要注意:
HTMLInputElement.defaultChecked
defaultChecked 使您能够完全绕过对HTMLInputElement 的checked 属性的搜索,因为它存储了一个基于该属性值的布尔值。这意味着您不必为与 get/set/removeAttribute 相关的 IE 构建提供草率的解决方案。稍后,还将添加 defaultValue 属性来满足类似的需求。
document.lastModified [非标准]
lastModified 将存储上次更改文档的时间。这是一个很酷的小功能,但用途有限。
HTMLDocument.title
title 将为您获取文档的标题。它的用途充其量只是一个小众市场。
关于您的 tbody 问题,如果您不提倡正确的 DOM 结构,今天的浏览器会添加 HTMLTableSectionElement (tbody)。您应该了解正确的表格标记,这样将来就不会出现问题了:)。
示例标记:
错误:
<table>
<!-- tbody will be inserted here and will wrap the tr -->
<tr>
<td>Hello, World!</tr>
</tr>
</table>
对:
<table>
<tbody>
<tr>
<td>Hello, World!</td>
</tr>
</tbody>
</table>
演示:http://jsbin.com/exomub/edit#preview
总结
需要强调的主要一点是,DOM Level 0 的大部分内容都在 DOM Levels 1 和 2 中进行了标准化。这意味着浏览器支持非常广泛(因为它确实很旧)。除了旧浏览器版本中的一些边缘情况外,使用它不应该有太多的担忧。归根结底,这是您的选择。
我想补充一点,我只是非常短暂地——在过去——受雇于使用 HTML/JavaScript 进行开发。我把它作为一种爱好,所以我不知道关于浏览器/项目出错的“恐怖故事”。
我希望这能解决一些问题。
-马特
ElementNode - 带有nodeType == 1的节点
HTMLCollection - 由浏览器收集的类似实时数组的 NodeList