获取 dom 元素
getElementById
根据 HTML 标签的 id 属性的值来获取对应的元素 HTMLElement
<p id="foo">bar</p>
<script>
var pFoo = document.getElementById("foo");
</script>
getElementsByTagName
根据 HTML 标签的标签名来获取对应的一组元素, 返回的是一个类数组 HTMLCollection
<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
<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
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
等
<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 变化而更新
<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>
遍历节点树
元素与节点
- 元素: 仅仅是指
html元素
HTMLElement
- 节点: 节点包括元素, mdn 文档
- 元素节点: HTML 元素, 也叫元素节点
HTMLElement
, 比如<p></p>
- 属性节点: html 标签上的属性
- 文本节点: 就是指元素中的文本内容 比如:
<p>文本内容<p>
中间的文本内容
就是文本节点
- 注释节点: 就是指 html 代码中的注释 , 比如:
<!--这是一个注释-->
- document 节点: 当前页面的 document
- DocumentFragment 节点:
- 元素节点: HTML 元素, 也叫元素节点
DOM 节点相关文档
DOM 文档
MDN DOM 文档 - Document Object ModelDevDocs DOM 文档 - Document Object Modelw3.org DOM 文档
Node 文档
MDN 节点文档 - NodeMDN 元素节点文档 - ElementMDN HTML 元素节点文档 - HTMLElement
以上各类节点的继承关系
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
<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
, 包括文本节点, 元素节点, 属性节点, 注释节点等
<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 是节点, 但是不是元素节点
<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
属性
<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
获取第一个子元素节点/最后一个子元素节点
<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) 一个同级的元素
<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 保证代码的兼容性
获取节点信息的属性
nodeName(readonly) - Node
获取节点的名称, 只读属性, 只有类型是 Element 的节点的名字是 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 返回 该属性的属性值
<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
返回一个整数,其代表的是节点类型。其所有可能的值请参考 节点类型常量.
手动实现
获取所有的元素子节点
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;
}