在现代JavaScript应用程序中使用DOM Level 0的最佳实践

Sea*_*lan 23 javascript jquery dom

在现代JavaScript应用程序中使用DOM Level 0集合是否有一套商定的"最佳实践" ?(document.forms,document.images等)

在使用jQuery的应用程序中,我注意到,比如使用$(...).html()切换底层节点而不是使用来改变下拉列表的内容element.options[].这是因为最好避免使用DOM 0集合,还是因为jQuery使更改底层DOM结构变得更容易?

编辑:我想部分问题包括旧功能是否可靠的跨浏览器.我记得,曾经有一段时间,IE会<tbody>自动添加标签到你的桌子,而firefox则不会.这使得走在dom tree痛苦的跨浏览器.同样,在更改集合中的选项时element.options[]遇到问题.这些人是否可靠跨浏览器?

小智 16

首先,很好的问题.

DOM Level 0-1功能是我最喜欢的工具箱.支持是巨大的.我将在下面突出显示DOM Level 0的每个子集的优缺点:

DOM级别0事件

由于这些是作为ElementNode的属性添加的,因此您只能拥有一个处理程序.对于某些情况(例如:事件委托),这是繁重的.但是,我觉得DOM足够多(特别是当你的项目变大时)为DOM 0级处理程序提供足够的空间.没有库/框架来平滑旧浏览器,DOM Level 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;
Run Code Online (Sandbox Code Playgroud)

这是一种非常简单的选择元素的方法,也是Event.currentTarget的替代方法 ;

这里有关于DOM Level 0事件与DOM Level 2事件的讨论:[ link ]


DOM Level 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>
Run Code Online (Sandbox Code Playgroud)

有许多DOM Level 0方法可以解决这个问题.

  1. var foo = document.forms.foo; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">

    演示:http://jsbin.com/udozoz/0edit#preview

  2. var foo = document.forms[0]; //<form id="foo" onsubmit="return false;" method="post" name="foo" action="./">

    演示:http://jsbin.com/udozoz/2/edit#preview

  3. 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>
Run Code Online (Sandbox Code Playgroud)

你可以使用这个简单的代码,让每个单选按钮的name属性值为"selectable":

  1. 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]
    
    Run Code Online (Sandbox Code Playgroud)

    演示:http://jsbin.com/upiyom/edit#preview

  2. var foo = document.forms.foo;
    var selectables = foo.selectable;
    console.log(selectables); //[input#select_1 a, input#select_2 b, input#select_3 c]
    
    Run Code Online (Sandbox Code Playgroud)

    演示:http://jsbin.com/upiyom/2/edit#preview

选项2使您可以完全绕过elements HTMLCollection.虽然肯定不如选项1那么清晰,但它仍然在今天使用.

自从引入DOM Level 0以来,HTMLCollections已经变得更加人口稠密,而且更加多样化.例如,看看可用于表的HTMLCollections.这令人震惊.有HTMLTableElement.rows,HTMLTableElement.tBodies,HTMLTableSectionElement(thead,tbody,tfoot).rowsHTMLTableRowElement.cells.这些集合非常强大,并且使用表格进行DOM遍历变得更加简单(允许您使用它们).


DOM级别0属性

尽管ElementNodes上的属性在DOM级别0中并不像现在这样多,但仍有一些宝石需要注意:

HTMLInputElement.defaultChecked

defaultChecked使您能够绕过通过搜索HTMLInputElementchecked属性,完全是因为它存储了基于该属性的值一个布尔值.这意味着您不必通过与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>
Run Code Online (Sandbox Code Playgroud)

对:

<table>
    <tbody>
        <tr>
            <td>Hello, World!</td>
        </tr>
    </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

演示:http://jsbin.com/exomub/edit#preview


摘要

需要被驱动回家的要点是DOM级别0的大多数都是在DOM级别1和2中标准化的.这意味着浏览器支持是广泛的(因为它确实很旧).除了旧浏览器版本中的一些边缘情况之外,不应该过多担心使用它.在一天结束时,这是你的选择.

我想补充一点,我过去只是非常简短地使用HTML/JavaScript进行开发.我这是一个爱好,所以我不知道有关浏览器/项目出错的"恐怖故事".

我希望这清除了一些事情.

-Matt

ElementNode - 节点nodeType == 1

HTMLCollection - 浏览器收集的类似实时阵列的NodeList


Fré*_*idi 5

这是一个非常有趣的问题.这是我的两分钱.

首先,它可能不言而喻,但这取决于你正在编写代码.专业程序员的目标是遵循公司范围内(或者,对于大型公司,团队范围内)最佳实践,如果这些准则不鼓励或禁止DOM级别0,那么您不应该使用它.如果它被允许或根本没有被提及,那么该决定将解决为个人选择,例如您自己的代码.

现在,如果您愿意,没有明显的技术缺陷阻止您使用0级.例如,如果迭代比element.options任何慢于element.getElementsByTagName("option")或过慢,我会感到惊讶$("option", element).第一种语法也可以说比替代语言更具可读性.

浏览器支持也不是问题.0级比污垢更老,并且在太阳下每个脚本感知浏览器都支持超过十年.

但是,以上是关于选择,而不是效率,这是你的问题的后半部分.事实上,你可以遍历element.options$("option", element)$(element).children("option")有或多或少相同的效率,但如果你必须做繁重的工作(例如,消灭现有的<option>元素,并添加新的),然后使用element.innerHTML$(element).html()肯定会更快.

这是因为innerHTML Level 0属性和html() jQuery方法(在innerHTML内部使用)都将所有标记解析和DOM操作委托给浏览器,浏览器通常用较低级别的语言编写,并 针对这些任务进行了大量优化.<option>在Javascript循环中逐个删除元素总是比较慢,在这种情况下,使用DOM Level 0或jQuery的所有铃声和口哨绝对没有区别.