Element
对象对应网页的HTML标签元素。每一个HTML标签元素,在DOM树上都会转化成一个Element
节点对象(以下简称元素节点)。
元素节点的nodeType
属性都是1,但是不同HTML标签生成的元素节点时不一样的。JS内部使用不同的构造函数,生成不同的Element
节点,比如<a>
标签的节点对象由HTMLAnchorElement()
构造函数生成,<button>
标签的节点对象由HTMLButtonElement()
构造函数生成。因此,元素节点不是一种对象,而是一组对象。
一、与元素本身特征相关的属性
以下属性与元素本身的特征相关。
1.1、Element.attributes
Element.attributes
属性返回一个类似数组的对象,成员是当前元素节点的所有属性节点。下一节将详细介绍。
1.2、Element.id,Element.tagName
Element.id
属性返回指定元素的id
属性,该属性可读写。
Element.tagName
属性返回指定元素的大写标签名,与nodeName
属性的值相等。
// HTML代码为
// <span id="myspan">Hello</span>
var span = document.getElementById('span');
span.id // "myspan"
span.tagName // "SPAN"
1.3、Element.innerHTML
Element.innerHTML
属性返回该元素包含的HTML代码。该属性可读写,常用来设置某个节点的内容。
如果将该属性设为空,等于删除它包含的所有节点。
el.innerHTML = '';
上面代码等于将el
节点变成了一个空节点,el
原来包含的节点被全部删除。
注意,如果文本节点中包含&
、小于号和大于号,innerHTML
属性会将它们转为实体形式&
、<
、>
。
// HTML代码如下 <p id="para"> 5 > 3 </p>
document.getElementById('para').innerHTML
// 5 > 3
由于上面这个原因,导致用innerHTML
插入<script>
标签,不会被执行。
var name = "<script>alert('haha')</script>";
el.innerHTML = name;
上面代码将脚本插入内容,脚本并不会执行。但是,innerHTML
还是有安全风险的。
var name = "<img src=x onerror=alert(1)>";
el.innerHTML = name;
上面代码中,alert
方法是会执行的。因此为了安全考虑,如果插入的事文本,最好用textContent
属性代替innerHTML
。
1.4、Element.outerHTML
Element.outerHTML
属性返回一个字符串,内容为指定元素节点的所有HTML代码,包括它自身和包含的所有子元素。
// HTML代码如下
// <div id="d"><p>Hello</p></div>
d = document.getElementById('d');
d.outerHTML
// '<div id="d"><p>Hello</p></div>'
outerHTML
属性是可读写的,对它进行赋值,等于替换掉当前元素。
// HTML代码如下
// <div id="container"><div id="d">Hello</div></div>
container = document.getElementById('container');
d = document.getElementById("d");
container.firstChild.nodeName // "DIV"
d.nodeName // "DIV"
d.outerHTML = '<p>Hello</p>';
container.firstChild.nodeName // "P"
d.nodeName // "DIV"
上面代码中,outerHTML
属性重新赋值以后,内层的div元素就不存在了,被p元素替换了。但是,变量d依然指向原来的div元素,这表示被替换的DIV元素还存在于内存中。
1.5、Element.className,Element.classList
className
属性用来读写当前元素节点的class
属性。它的值是一个字符串,每个class
之间用空格分割。
classList
属性则返回一个类似数组的对象,当前元素节点的每个class
就是这个对象的一个成员。
<div class="one two three" id="myDiv"></div>
上面这个div元素节点对象的className属性和classList属性,分别如下。
document.getElementById('myDiv').className
// "one two three"
document.getElementById('myDiv').classList
// {
// 0: "one"
// 1: "two"
// 2: "three"
// length: 3
// }
从上面代码可以看出,className
属性返回一个空格分隔的字符串,而classList
属性指向一个类似数组的对象,该对象的length
属性(只读)返回当前元素的class
数量。
classList对象有下列方法。
add():增加一个class。
remove():移除一个class。
contains():检查当前元素是否包含某个class。
toggle():将某个class移入或移出当前元素。
item():返回指定索引位置的class。
toString():将class的列表转为字符串。
myDiv.classList.add('myCssClass');
myDiv.classList.add('foo', 'bar');
myDiv.classList.remove('myCssClass');
myDiv.classList.toggle('myCssClass'); // 如果myCssClass不存在就加入,否则移除
myDiv.classList.contains('myCssClass'); // 返回 true 或者 false
myDiv.classList.item(0); // 返回第一个Class
myDiv.classList.toString();
下面比较一下,className和classList在添加和删除某个类时的写法。
// 添加class
document.getElementById('foo').className += 'bold';
document.getElementById('foo').classList.add('bold');
// 删除class
document.getElementById('foo').classList.remove('bold');
document.getElementById('foo').className =
document.getElementById('foo').className.replace(/^bold$/, '');
toggle
方法可以接受一个布尔值,作为第二个参数。如果为true
,则添加该属性;如果为false
,则去除该属性。
el.classList.toggle('abc', boolValue);
// 等同于
if (boolValue){
el.classList.add('abc');
} else {
el.classList.remove('abc');
}
二、盒状模型相关属性
2.1、Element.clientHeight,Element.clientWidth
Element.clientHeight
属性返回元素节点可见部分的高度,Element.clientWidth
属性返回元素节点可见部分的宽度。所谓可见部分,指的是不包括溢出的大小,只返回该元素在容器中占据的大小,对于有滚动条的元素来说,它们等于滚动条围起来的区域大小。这两个属性的值包括Padding、但不包括滚动条、边框和Margin,单位为像素。这两个属性可以计算得到,等于元素的CSS高度(或宽度)加上CSS的padding,减去滚动条(如果存在)。
对于整张网页来说,当前可见高度(即视口高度)要从document.documentElement
对象(即<html>
节点)上获取,等同于window.innerHeight
属性减去水平滚动条的高度。没有滚动条时,这两个值是相等的;有滚动条时,前者小于后者。
2.2、Element.clientLeft,Element.clientTop
2.3、Element.scrollHeight,Element.scrollWidth
2.4、Element.scrollLeft,Element.scrollTop
2.5、Element.offsetHeight,Element.offsetWidth
2.6、Element.offsetLeft,Element.offsetTop
2.7、Element.style
每个元素节点都有style用来读写该元素的行内样式信息。
2.8、总结
三、返回元素节点相关节点的属性
以下属性返回元素节点的相关节点。
3.1、Element.children,Element.childElementCount
Element.children
属性返回一个HTMLCollection
对象,包括当前元素节点的所有子节点。它是一个类似数组的动态对象(实时反映网页元素的变化)。如果当前元素没有子元素,则返回的对象包含零个成员。
// para是一个p元素节点
if (para.children.length) {
var children = para.children;
for (var i = 0; i < children.length; i++) {
// ...
}
}
这个属性与Node.childNodes
属性的区别是,它只包括HTML元素类型的子节点,不包括其他类型的子节点。
Element.childElementCount
属性返回当前元素节点包含的子HTML元素节点的个数,与Element.children.length
的值相同。注意,该属性只计算HTML元素类型的子节点。
3.2、Element.firstElementChild,Element.lastElementChild
Element.firstElementChild
属性返回第一个HTML元素类型的子节点,Element.lastElementChild
返回最后一个HTML元素类型的子节点。
如果没有HTML类型的子节点,这两个属性返回null
。
3.3、Element.nextElementSibling,Element.previousElementSibling
Element.nextElementSibling
属性返回当前HTML元素节点的后一个同级HTML元素节点,如果没有则返回null
。
// 假定HTML代码如下
// <div id="div-01">Here is div-01</div>
// <div id="div-02">Here is div-02</div>
var el = document.getElementById('div-01');
el.nextElementSibling
// <div id="div-02">Here is div-02</div>
Element.previousElementSibling
属性返回当前HTML元素节点的前一个同级HTML元素节点,如果没有则返回null
。
3.4、Element.offsetParent
Element.offsetParent
属性返回当前HTML元素的最靠近的、并且CSS的position
属性不等于static
的父元素。如果某个元素的所有上层节点都将position
属性设为static
,则Element.offsetParent
属性指向<body>
元素。
该属性主要用于确定子元素的位置偏移,是Element.offsetTop
和Element.offsetLeft
的计算基准。
四、操作元素属性相关的方法
元素节点提供以下四个方法,用来操作HTML标签的属性。
- Element.getAttribute():读取指定属性
- Element.setAttribute():设置指定属性
- Element.hasAttribute():返回一个布尔值,表示当前元素节点是否有指定的属性
- Element.removeAttribute():移除指定属性
五、查找相关的方法
以下四个方法用来查找与当前元素节点相关的节点。这四个方法也部署在document
对象上,用法完全一致。
- Element.querySelector()
- Element.querySelectorAll()
- Element.getElementByTagName()
- Element.getElementByClassName()
上面四个方法只返回Element
子节点,因此可以采用链式写法。
document
.getElementById('header')
.getElementsByClassName('a')
5.1、Element.querySelector()
Element.querySelector
方法接受CSS选择器作为参数,返回父元素的第一个匹配的子元素。
var content = document.getElementById('content');
var el = content.querySelector('p');
上面代码返回content
节点的第一个p
元素。
需要注意的是,浏览器执行querySelector
方法时,是先在全局范围内搜索给定的CSS选择器,然后过滤出哪些属于当前元素的子元素。因此,会有一些违反直觉的结果。
<div>
<blockquote id="outer">
<p>Hello</p>
<div id="inner">
<p>World</p>
</div>
</blockquote>
</div>
那么,下面代码实际上会返回第一个p元素,而不是第二个。
var outer = document.getElementById('outer');
outer.querySelector('div p')
// <p>Hello</p>
5.2、Element.querySelectorAll()
Element.querySelectorAll
方法接受CSS选择器作为参数,返回一个NodeList
对象,包含所有匹配的子元素。
该方法的执行机制与querySelector
相同,也是先在全局范围内查找,再过滤出当前元素的子元素。因此,选择器实际上针对整个文档的。
5.3、Element.getElementsByTagName()
Element.getElementsByTagName
方法返回一个HTMLCollection
对象,成员是当前元素节点的所有匹配指定标签名的子元素。该方法与document.getElementsByTagName
方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
同样的,该方法的参数大小写不敏感。
5.4、Element.getElementsByClassName()
Element.getElementsByClassName
方法返回一个HTMLCollection
对象,成员是当前元素节点的所有匹配指定class的子元素。该方法与document.getElementsByClassName
方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
该方法的参数大小写敏感。
5.5、Element.closest()
Element.closest
方法返回当前元素节点的最接近的父元素(或者当前节点本身),条件是必须匹配给定的CSS选择器。如果不满足匹配,则返回null
。
//HTML代码
<article>
<div id="div-01">Here is div-01
<div id="div-02">Here is div-02
<div id="div-03">Here is div-03</div>
</div>
</div>
</article>
//JS代码
var el = document.getElementById('div-03');
el.closest("#div-02") // div-02
el.closest("div div") // div-03
el.closest("article > div") //div-01
el.closest(":not(div)") // article
上面代码中,由于closet
方法将当前元素节点也考虑在内,所以第二个closet
方法返回div-03
。
5.6、Element.match()
Element.match
方法返回一个布尔值,表示当前元素是否匹配给定的CSS选择器。
六、事件相关的方法
以下三个方法与Element节点的事件相关。这些方法都继承自EventTarget接口。
- Element.addEventListener():添加事件的回调函数
- Element.removeEventListener():移除事件监听函数
- Element.dispatchEvent():触发事件
element.addEventListener('click', listener, false);
element.removeEventListener('click', listener, false);
var event = new Event('click');
element.dispatchEvent(event);
七、其他方法
7.1、Element.scrollIntoView()
7.2、Element.getBoundingClientRect()
7.3、Element.getClientRects()
7.4、Element.insertAdjacentHTML()
7.5、Element.remove()
Element.remove
方法用于将当前元素节点从DOM树删除。
var el = document.getElementById('div-01');
el.remove();
7.6、Element.focus()
Element.focus
方法用于将当前页面的焦点,转移到指定元素上。
document.getElementById('my-span').focus();