Skip to content

获取 dom 元素

getElementById

根据 HTML 标签的 id 属性的值来获取对应的元素 HTMLElement

html
<p id="foo">bar</p>

<script>
  var pFoo = document.getElementById("foo");
</script>

getElementsByTagName

根据 HTML 标签的标签名来获取对应的一组元素, 返回的是一个类数组 HTMLCollection

html
<div>01</div>
<div>02</div>
<div>03</div>

<script>
  var divList = document.getElementsByTagName("div");
  console.info(divList); // [ div, div, div ]
</script>

getElementsByClassName

根据 HTML 标签的 class 属性的值来获取对应的一组元素, 返回的是一个类数组 HTMLCollection  IE8 以下是没有这个方法的, 如果要写兼容 IE8 的代码, 建议使用 querySelector

html
<div class="box">01</div>
<div class="box">02</div>
<div class="box">03</div>

<script>
  var boxList = document.getElementsByClassName("box");
  console.info(boxList); // [ div, div, div ]
</script>

封装 byClassName 兼容低版本 IE

javascript
Document.prototype.getElementsByClassName = Element.prototype.getElementsByClassName =
  document.getElementsByClassName ||
  function (className) {
    // function (className) { 现在的浏览器可能都支持了, 所以需要强行重写
    var allDoms = this.getElementsByTagName("*"),
      len = allDoms.length,
      res = [],
      item;

    for (var i = 0; i < len; i++) {
      item = allDoms[i];
      if (item.className.indexOf(className) !== -1) {
        res.push(item);
      }
    }
    return res;
  };

var items = document.getElementsByClassName("item");
console.info(items);

getElementsByName(不常用)

根据 HTML 标签的 name  属性的值来获取对应的一组元素, 返回的是一个类数组 NodeList  IE8 可以使用这个方法, 但是只能支持有 name  属性的标签, 比如: input iframe  等

html
<form action="">
  <input type="text" name="email" />
</form>

<script>
  var email = document.getElementsByName("email");
</script>

querySelector/querySelectAll

HTML5 新引入的 API, 但是可以兼容 IE8, 但是性能不如上面的那些方法 querySelector: 选中符合参数(css 选择器字符串)的第一个 html 元素, 返回的是一个 HTMLElement  querySelectorAll: 选中符合参数(css 选择器字符串)的所有 html 元素, 返回的是一个 NodeList  注意: querySelector 和 querySelectorAll 会有一个缓存的机制, 不会实时的随着 dom 变化而更新

html
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<script>
  var firstDiv = document.querySelector(".test"); // <div class="test">1</div>
  var allDiv = document.querySelectorAll(".test");
  console.log(allDiv); // [div, div, div]
  allDiv[0].remove();
  console.log(allDiv); // [div, div, div]

  // 会随着dom节点的变化而变化
  var getAllDiv = document.getElementsByClassName("test");
  console.log("getAllDiv: ", getAllDiv); // [div, div, div]
  getAllDiv[0].remove();
  console.log("getAllDiv: ", getAllDiv); // [div, div]
</script>

遍历节点树

元素与节点

  1. 元素: 仅仅是指 html元素 HTMLElement
  2. 节点: 节点包括元素, mdn 文档
    1. 元素节点: HTML 元素, 也叫元素节点 HTMLElement , 比如 <p></p>
    2. 属性节点: html 标签上的属性
    3. 文本节点: 就是指元素中的文本内容 比如: <p>文本内容<p>  中间的 文本内容  就是 文本节点
    4. 注释节点: 就是指 html 代码中的注释 , 比如: <!--这是一个注释-->
    5. document 节点: 当前页面的 document
    6. DocumentFragment 节点:

DOM 节点相关文档

DOM 文档

MDN DOM 文档 - Document Object ModelDevDocs DOM 文档 - Document Object Modelw3.org DOM 文档

Node 文档

MDN 节点文档 - NodeMDN 元素节点文档 - ElementMDN HTML 元素节点文档 - HTMLElement

以上各类节点的继承关系

dom.png

NodeList & HTMLCollection 文档

MDN 节点文档 - NodeListMDN 元素列表文档 - HTMLCollection

查询各个属性兼容性的文档

CanIUse: https://caniuse.com/ MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model

节点属性

包括 Node 和 Element 的属性

获取元素节点的属性

parentNode - Node

获取父级节点, 如果当前元素是 document  则, parentNode 的值为 null

html
<div id="app">
  <div class="test">
    <h2 class="title">JavaScript</h2>
  </div>
</div>
<script>
  var h2 = document.getElementsByClassName("title");
  h2 = h2[0];
  console.log(h2.parentNode); // <div class="test"></div>
</script>

childNodes - Node

获取所有子节点 NodeList, 包括文本节点, 元素节点, 属性节点, 注释节点等

html
<div id="app">
  <!-- test wrapper -->
  <div class="test">
    <h2 class="title">JavaScript</h2>
  </div>
  <p>texts</p>
</div>
<script>
  var app = document.getElementById("app");
  console.info(app.childNodes); // [text, comment, text, div, text, p, text] -> [回车, 注释, 回车, div.test, 回车, p, 回车]
</script>

parentElement - Element

获取父级元素节点, 如果当前的节点是 html, 则 parentElement 的值为 null 因为 document 是节点, 但是不是元素节点

html
<div id="app">
  <div class="test">
    <h2 class="title">JavaScript</h2>
  </div>
</div>
<script>
  var h2 = document.getElementsByClassName("title");
  h2 = h2[0];
  console.log(h2.parentElement); // <div class="test"></div>
</script>

children - Element

获取所有的子元素节点 HTMLCollection, 只有元素节点, 不包括其他类型的节点 Q: 如何直接获取 element.children.length  的值 A: 使用 childElementCount 属性

html
<div id="app">
  <!-- test wrapper -->
  <div class="test">
    <h2 class="title">JavaScript</h2>
  </div>
  <p>texts</p>
</div>
<script>
  var app = document.getElementById("app");
  console.info(app.children); // [div, p] -> [div.test, p]
</script>

firstElementChild/lastElementChild - Element

获取第一个子元素节点/最后一个子元素节点

html
<div id="app">
  <!-- test wrapper -->
  <div class="test">
    <h2 class="title">JavaScript</h2>
  </div>
  <p>texts</p>
</div>
<script>
  var app = document.getElementById("app");
  console.info(app.firstElementChild); // <div class="test">..</div>
  console.info(app.lastElementChild); // <p>texts</p>
</script>

previousElementSibling/nextElementSibling - Element

获取前面(previousElementSibling)/后面(nextElementSibling) 一个同级的元素

html
<div id="app">
  <p class="before1">before1</p>
  <p class="before2">before2</p>
  <h2 id="target">target</h2>
  <p class="after1">after1</p>
  <p class="after2">after2</p>
</div>
<script>
  var target = document.getElementById("target");
  console.info(target.previousElementSibling); // <p class="before2">before2</p>
  console.info(target.nextElementSibling); // <p class="after1">after1</p>
</script>

注意: 兼容性问题及封装

因为: children  可以兼容到 IE7, 而 previousElementSibling/nextElementSibling, firstChild/lastChild, parentChild 这些属性 IE9 及其以下版本浏览器都不支持 所以: 建议使用 parentNode  和 children  来自己封装, 避免使用这些兼容性不好的 API 保证代码的兼容性

获取节点信息的属性

Node - MDN 文档

nodeName(readonly) - Node

获取节点的名称, 只读属性, 只有类型是 Element 的节点的名字是 html 的标签名, 其他的是 #类型  格式

html
<div id="app">
  文本
  <!-- 注释 -->
  <div class="test">test</div>
</div>
<script>
  console.info(document.nodeName); // #document

  var app = document.getElementById("app");
  console.info(app.firstChild.nodeName); // #text
  app.firstChild.nodeName = "testNodeName";
  console.info(app.firstChild.nodeName); // #text

  console.info(app.childNodes[1].nodeName); // DIV
  console.info(app.firstElementChild.nodeName); // #comment
</script>

nodeValue - Node

对于元素节点来说, nodeValue 返回 null 对于 text, comment, 和其他继承于 CharacterData(CDATA)类的节点来说, nodeValue 返回该节点的 文本内容 对于属性节点来说, nodeValue 返回 该属性的属性值

html
<div id="app">
  这是文本
  <!-- 这是注释 -->
  <div class="test">test</div>
</div>

<script>
  // 文档节点
  console.info(document.nodeValue); // null

  // 元素节点
  var app = document.getElementById("app");
  console.info(app.nodeValue); // null

  // 文本节点
  console.info(app.childNodes[0].nodeValue); // 这是文本

  // 注释节点
  console.info(app.childNodes[1].nodeValue); // 这是注释
</script>

nodeType(readonly) - Node

返回一个整数,其代表的是节点类型。其所有可能的值请参考  节点类型常量. dom-consts

手动实现

获取所有的元素子节点

javascript
function getElementChildNodes(node) {
  var nodes = [];
  if (!(node instanceof Node)) {
    // 必须是 Node 的实例
    return nodes;
  }

  if (!node.hasChildNodes()) {
    // 如果没有 children 属性, 或者没有任何子元素
    return nodes;
  }

  var item,
    children = node.childNodes;
  for (var i = 0; i < children.length; i++) {
    item = children[i];
    item.nodeType === Node.ELEMENT_NODE && nodes.push(item);
  }
  return nodes;
}

Released under the MIT License.