zoukankan      html  css  js  c++  java
  • 跟随标准与Webkit源码探究DOM -- 获取元素之getElementsByTagName

    按照标签名获取元素 -- getElementsByTagName

    标准

    • DOM 1在ElementDocument两个interface中均有定义,原型NodeList getElementsByTagName(in DOMString tagname),指明按照先序遍历遇到的顺序排列,不会抛出任何异常,参数"*"返回对应document或者element下所有元素。注意这里指明返回的是一个live的仅含有ElementNodeList
    • DOM 2里定义仍在ElementDocument,增加了带namespace的NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName)ElementDocument),引入了localName的概念(只有ELEMENT_NODEATTRIBUTE_NODE才能有)。
    • DOM 3(DocumentElement)特别声明XML应当对标签名的大小写敏感,非XML则依照文档类型自己对待大小写的风格来决定是否敏感。实际上浏览器对HTML都会先将标签转统一换成成小写后再去匹配,所以只能匹配到实际标签名为小写的元素。
    • WHATWG (Document ,Element)将返回类型修改为了HTMLCollection,并解释了通过localName产生HTMLCollection的算法。注意算法的第二步实际上规定了在非HTML文档里,标签名大小写敏感;而在HTML文档里,任何大小写的标签都会被统一转换成小写后再去匹配,所以只能匹配到实际标签名为小写的元素。
    • DOM 4(DocumentElement) 目前与 WHATWG 基本一致

    DOM Tree Accessors

    DOM 1DOM 2HTMLDocument interface 里定义了一系列"DOM Tree Accessors"

    • readonly attribute HTMLCollection images
    • readonly attribute HTMLCollection applets
    • readonly attribute HTMLCollection links
    • readonly attribute HTMLCollection forms
    • readonly attribute HTMLCollection anchors
    • attribute HTMLElement body

    这意味着在HTML文档里可以用document.images获得所有<img>元素,用document.links获取所有带有href属性的<a>元素,用document.links获取所有带有name属性的<a>元素,用document.forms获取所有<form>元素。另外获取<body>可以使用document.body

    自 HTML5(W3CWHATWG)开始还定义了document.head,删去了document.anchors,增加了获取<embed>document.embeds和目前与之相同的document.plugins,以及获取<script>document.scripts

    DOM 1 便在Document 定义了document.documentElement来获取根元素并保留至今,在HTML文档里即<html>元素。

    兼容性

    • IE 5.5 不支持*作为参数获取所有元素。IE6以上的IE以及各大浏览器均按照标准实现了getElementsByTagName
    • 虽然document.scriptsdocument.embedsdocument.plugins直到HTML5才标准化,不过各版本IE和其他浏览器的现行版本都支持
    • document.head需要IE9+才支持。其他DOM Tree Accessor基本在各版本IE和现行的浏览器里都有支持。

    Webkit 代码分析

    类似getElementsByNamegetElementsByTagNameContainerNode里实现。由于标准里对XML的特殊规定,这里会依据文档类型,换用TagNodeList或者HTMLTagNodeList作为NodeListsNodeData::addCacheWithAtomicName<>的template specialization(参见WebCore/dom/ContainerNode.cpp)。

    TagNodeList实现的elementMatches是:

    if (m_localName != starAtom && m_localName != element.localName())
        return false;
    return m_namespaceURI == starAtom || m_namespaceURI == element.namespaceURI();

    这里starAtom就是标准里说的*。先比对localName是否相符或为*,然后比对namespaceURI是否相符或为*。由于没有大小写转换步骤,所以遵循标准,是大小写敏感的。注意这里比对namespaceURI的步骤相对于getElementsByTagName是多余的,之所以加上是因为getElementsByTagNameNS也用TagNodeList,这样就可以偷懒不用再多写一个比对namespaceURI的版本。不过getElementsByTagNameNS用的其实是addCacheWithQualifiedName而不是addCacheWithAtomicName,其实addCacheWithQualifiedNameaddCacheWithAtomicName的不同也就是它拿TagNodeList直接提前做好了template specification而已(参见WebCore/dom/NodeRareData.h

    HTMLTagNodeList实现的elementMatches是:

    if (m_localName == starAtom)
        return true;
    const AtomicString& localName = element.isHTMLElement() ? m_loweredLocalName : m_localName;
        return localName == element.localName();

    按照标准所说,如果被比对的元素是HTML namespace里的,转换为小写再比较。注意这里没有比对namespaceURI,毕竟getElementsByTagNameNS不用它(标准里没有指明getElementsByTagNameNS需要转换大小写,所以用TagNodeList那个大小写敏感的过滤足矣)。

  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/joyeecheung/p/4115426.html
Copyright © 2011-2022 走看看