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

时间:2011-07-05 16:39:05

标签: javascript jquery dom

在现代JavaScript应用程序中使用DOM Level 0 collections是否有一套商定的“最佳实践”? (document.formsdocument.images等。)

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

编辑:我想部分问题包括旧功能是否可靠的跨浏览器。我记得,曾经有一段时间,IE会自动将<tbody>标签添加到你的桌面,而firefox则不会。这使得走在dom tree痛苦的跨浏览器。同样,element.options[]problems when changing the options in the collection。这些人是否可靠跨浏览器?

5 个答案:

答案 0 :(得分: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;

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

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


DOM Level 0 HTMLCollections

Bar none, 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方法可以解决这个问题。

  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

  4. 当然,方法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属性值为“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]
      

      演示: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]
      

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

    3. 选项2可让您完全绕过elements HTMLCollection 。虽然肯定不如选项1那么明确,但它仍然在今天使用。

      自从引入DOM Level 0以来,

      HTMLCollections 变得更加人性化,而且更加多样化。例如,看一下表格中可用的 HTMLCollections 。这令人震惊。有HTMLTableElement.rowsHTMLTableElement.tBodiesHTMLTableSectionElement (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>
      

      右:

      <table>
          <tbody>
              <tr>
                  <td>Hello, World!</td>
              </tr>
          </tbody>
      </table>
      

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


      摘要

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

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

      我希望这能清除一些事情。

      -Matt

      ElementNode - nodeType == 1

      的节点

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

答案 1 :(得分:5)

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

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

现在,如果你愿意,没有明显的技术缺陷阻止你使用0级。例如,如果迭代element.optionselement.getElementsByTagName("option")$("option", element)慢,我会感到惊讶。第一种语法也可以说比其他选择更多可读。

浏览器支持也不是问题。 0级是older than dirt,并且在太阳下每个脚本感知浏览器都支持了十多年。

但是,以上是关于选择,而不是效率,这是你问题的后半部分所关注的。实际上,您可以以或多或少相同的效率迭代element.options$("option", element)$(element).children("option"),但如果您需要做大量工作(例如,消除现有的{{1}元素并添加新元素),然后使用<option>element.innerHTML肯定会更快。

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

答案 2 :(得分:3)

我首先要说的是,我不知道任何“官方”声明,例如“DOM Level 0被视为有害”。这只是我自己的看法。

我认为这取决于具体情况。

我遇到的问题是,使用documents.formsdocuments.images这样的集合来定位特定元素时,尤其是动态生成/修改过的文档存在问题。每当我看到有人写document.forms[0]时,我都会畏缩。

当前,甚至不那么流行的浏览器通过getElementsByTagName等函数提供了模拟相同行为的能力,但是以更通用和可重用的方式。当然,当你在混合中添加jQuery时,根本没有理由使用这些集合。

我遇到的例外情况是,当您在非jQuery环境中工作并且正在访问selectElement.optionstbodyElement.rows之类的内容时。在这些情况下,当您进行添加或删除项目等基本操作时,它确实更简单。

答案 3 :(得分:3)

  

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

这可以很容易地解释。 95%的jQuery开发人员不了解DOM API存在或可以使用的事实。

jQuery被滥用于DOM可以更容易地做的事情这一事实仅仅是由于没有学习DOM的人造成的。

我个人会说使​​用DOM 0,但话说回来,我个人会说使​​用DOM shim并且不使用jQuery。这都是一个选择问题。

做最多 可维护的

答案 4 :(得分:1)

无论好坏,我使用纯DOM级别0功能主要用于调试。检查document.forms [0]。输入元素有时会更快。

当我正在检查一些使用某些深奥(或根本不为我所知)框架的页面时,我也使用了这些功能。我没有时间深入研究这些抽象,只是直接检查馆藏。

我相信你会更好地了解所有这些DOM零库,但如果你知道所有这些现代纯DOM不知道哪个级别它是exaclty级API,那就更好了。例如,ClassList集合很好。我的意思是,如果你使用的是框架,你应该总是知道,为什么完全需要它。

相关问题