DOM 下
约 17385 字大约 58 分钟
JavaScript
2025-05-15
Element 节点
Element节点对象对应网页的 HTML 元素。每一个 HTML 元素,在 DOM 树上都会转化成一个Element节点对象(以下简称元素节点)。
元素节点的nodeType属性都是1。
var p = document.querySelector('p');
p.nodeName // "P"
p.nodeType // 1Element对象继承了Node接口,因此Node的属性和方法在Element对象都存在。
此外,不同的 HTML 元素对应的元素节点是不一样的,浏览器使用不同的构造函数,生成不同的元素节点,比如<a>元素的构造函数是HTMLAnchorElement(),<button>是HTMLButtonElement()。因此,元素节点不是一种对象,而是许多种对象,这些对象除了继承Element对象的属性和方法,还有各自独有的属性和方法。
实例属性
元素特性
元素特性的相关属性
(1)Element.id
Element.id属性返回指定元素的id属性,该属性可读写。
// HTML 代码为 <p id="foo">
var p = document.querySelector('p');
p.id // "foo"注意,id属性的值是大小写敏感,即浏览器能正确识别<p id="foo">和<p id="FOO">这两个元素的id属性,但是最好不要这样命名。
(2)Element.tagName
Element.tagName属性返回指定元素的大写标签名,与nodeName属性的值相等。
// HTML代码为
// <span id="myspan">Hello</span>
var span = document.getElementById('myspan');
span.id // "myspan"
span.tagName // "SPAN"(3)Element.dir
Element.dir属性用于读写当前元素的文字方向,可能是从左到右("ltr"),也可能是从右到左("rtl")。
(4)Element.accessKey
Element.accessKey属性用于读写分配给当前元素的快捷键。
// HTML 代码如下
// <button accesskey="h" id="btn">点击</button>
var btn = document.getElementById('btn');
btn.accessKey // "h"上面代码中,btn元素的快捷键是h,按下Alt + h就能将焦点转移到它上面。
(5)Element.draggable
Element.draggable属性返回一个布尔值,表示当前元素是否可拖动。该属性可读写。
(6)Element.lang
Element.lang属性返回当前元素的语言设置。该属性可读写。
// HTML 代码如下
// <html lang="en">
document.documentElement.lang // "en"(7)Element.tabIndex
Element.tabIndex属性返回一个整数,表示当前元素在 Tab 键遍历时的顺序。该属性可读写。
tabIndex属性值如果是负值(通常是-1),则 Tab 键不会遍历到该元素。如果是正整数,则按照顺序,从小到大遍历。如果两个元素的tabIndex属性的正整数值相同,则按照出现的顺序遍历。遍历完所有tabIndex为正整数的元素以后,再遍历所有tabIndex等于0、或者属性值是非法值、或者没有tabIndex属性的元素,顺序为它们在网页中出现的顺序。
(8)Element.title
Element.title属性用来读写当前元素的 HTML 属性title。该属性通常用来指定,鼠标悬浮时弹出的文字提示框。
元素状态
元素状态的相关属性
(1)Element.hidden
Element.hidden属性返回一个布尔值,表示当前 HTML 元素的hidden属性的值。该属性可读写,用来控制当前元素是否可见。
var btn = document.getElementById('btn');
var mydiv = document.getElementById('mydiv');
btn.addEventListener('click', function () {
mydiv.hidden = !mydiv.hidden;
}, false);注意,该属性与 CSS 设置是互相独立的。CSS 对当前元素可见性的设置,Element.hidden并不能反映出来。也就是说,这个属性并不能用来判断当前元素的实际可见性。
CSS 设置的优先级高于Element.hidden。如果 CSS 指定了该元素不可见(display: none)或可见(visibility: visible),那么Element.hidden并不能改变该元素实际的可见性。换言之,这个属性只在 CSS 没有明确设定当前元素的可见性时才有效。
(2)Element.contentEditable
HTML 元素可以设置contentEditable属性,使得元素的内容可以编辑。
<div contenteditable>123</div>上面代码中,<div>元素有contenteditable属性,因此用户可以在网页上编辑这个区块的内容。
Element.contentEditable属性返回一个字符串,表示是否设置了contenteditable属性,有三种可能的值。该属性可写。
true:元素内容可编辑false:元素内容不可编辑inherit:元素是否可编辑,继承了父元素的设置
(3)Element.isContentEditable
Element.isContentEditable属性返回一个布尔值,同样表示是否设置了contenteditable属性。该属性只读。
Element.attributes
Element.attributes属性返回一个类似数组的对象,成员是当前元素节点的所有属性节点。
var p = document.querySelector('p');
var attrs = p.attributes;
for (var i = attrs.length - 1; i >= 0; i--) {
console.log(attrs[i].name + '->' + attrs[i].value);
}上面代码遍历p元素的所有属性。
Element.className
className属性用来读写当前元素节点的class属性。它的值是一个字符串,每个class之间用空格分割。
Element.classList
classList属性返回一个类似数组的对象,当前元素节点的每个class就是这个对象的一个成员。
// HTML 代码 <div class="one two three" id="myDiv"></div>
var div = document.getElementById('myDiv');
div.className
// "one two three"
div.classList
// {
// 0: "one"
// 1: "two"
// 2: "three"
// length: 3
// }classList对象有下列方法。
add():增加一个 class。remove():移除一个 class。contains():检查当前元素是否包含某个 class。toggle():将某个 class 移入或移出当前元素。item():返回指定索引位置的 class。toString():将 class 的列表转为字符串。
var div = document.getElementById('myDiv');
div.classList.add('myCssClass');
div.classList.add('foo', 'bar');
div.classList.remove('myCssClass');
div.classList.toggle('myCssClass'); // 如果 myCssClass 不存在就加入,否则移除
div.classList.contains('myCssClass'); // 返回 true 或者 false
div.classList.item(0); // 返回第一个 Class
div.classList.toString();下面比较一下,className和classList在添加和删除某个 class 时的写法。
var foo = document.getElementById('foo');
// 添加class
foo.className += 'bold';
foo.classList.add('bold');
// 删除class
foo.classList.remove('bold');
foo.className = foo.className.replace(/^bold$/, '');toggle方法可以接受一个布尔值,作为第二个参数。如果为true,则添加该属性;如果为false,则去除该属性。
el.classList.toggle('abc', boolValue);
// 等同于
if (boolValue) {
el.classList.add('abc');
} else {
el.classList.remove('abc');
}Element.dataset
网页元素可以自定义data-属性,用来添加数据。
<div data-timestamp="1522907809292"></div>上面代码中,<div>元素有一个自定义的data-timestamp属性,用来为该元素添加一个时间戳。
Element.dataset属性返回一个对象,可以从这个对象读写data-属性。
// <article
// id="foo"
// data-columns="3"
// data-index-number="12314"
// data-parent="cars">
// ...
// </article>
var article = document.getElementById('foo');
article.dataset.columns // "3"
article.dataset.indexNumber // "12314"
article.dataset.parent // "cars"注意,dataset上面的各个属性返回都是字符串。
HTML 代码中,data-属性的属性名,只能包含英文字母、数字、连词线(-)、点(.)、冒号(:)和下划线(_)。它们转成 JavaScript 对应的dataset属性名,规则如下。
- 开头的
data-会省略。 - 如果连词线后面跟了一个英文字母,那么连词线会取消,该字母变成大写。
- 其他字符不变。
因此,data-abc-def对应dataset.abcDef,data-abc-1对应dataset["abc-1"]。
除了使用dataset读写data-属性,也可以使用Element.getAttribute()和Element.setAttribute(),通过完整的属性名读写这些属性。
var mydiv = document.getElementById('mydiv');
mydiv.dataset.foo = 'bar';
mydiv.getAttribute('data-foo') // "bar"Element.innerHTML
Element.innerHTML属性返回一个字符串,等同于该元素包含的所有 HTML 代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括<HTML>和<body>元素。
如果将innerHTML属性设为空,等于删除所有它包含的所有节点。
el.innerHTML = '';上面代码等于将el节点变成了一个空节点,el原来包含的节点被全部删除。
注意,读取属性值的时候,如果文本节点包含&、小于号(<)和大于号(>),innerHTML属性会将它们转为实体形式&、<、>。如果想得到原文,建议使用element.textContent属性。
// HTML代码如下 <p id="para"> 5 > 3 </p>
document.getElementById('para').innerHTML
// 5 > 3写入的时候,如果插入的文本包含 HTML 标签,会被解析成为节点对象插入 DOM。注意,如果文本之中含有<script>标签,虽然可以生成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。
Element.outerHTML
Element.outerHTML属性返回一个字符串,表示当前元素节点的所有 HTML 代码,包括该元素本身和所有子元素。
// HTML 代码如下
// <div id="d"><p>Hello</p></div>
var d = document.getElementById('d');
d.outerHTML
// '<div id="d"><p>Hello</p></div>'outerHTML属性是可读写的,对它进行赋值,等于替换掉当前元素。
// HTML 代码如下
// <div id="container"><div id="d">Hello</div></div>
var container = document.getElementById('container');
var d = document.getElementById('d');
container.firstChild.nodeName // "DIV"
d.nodeName // "DIV"
d.outerHTML = '<p>Hello</p>';
container.firstChild.nodeName // "P"
d.nodeName // "DIV"上面代码中,变量d代表子节点,它的outerHTML属性重新赋值以后,内层的div元素就不存在了,被p元素替换了。但是,变量d依然指向原来的div元素,这表示被替换的DIV元素还存在于内存中。
注意,如果一个节点没有父节点,设置outerHTML属性会报错。
Element.clientHeight
Element.clientHeight属性返回一个整数值,表示元素节点的 CSS 高度(单位像素),只对块级元素生效,对于行内元素返回0。如果块级元素没有设置 CSS 高度,则返回实际高度。
除了元素本身的高度,它还包括padding部分,但是不包括border、margin。如果有水平滚动条,还要减去水平滚动条的高度。注意,这个值始终是整数,如果是小数会被四舍五入。
Element.clientWidth
Element.clientWidth属性返回元素节点的 CSS 宽度,同样只对块级元素有效,也是只包括元素本身的宽度和padding,如果有垂直滚动条,还要减去垂直滚动条的宽度。
document.documentElement的clientHeight属性,返回当前视口的高度(即浏览器窗口的高度),等同于window.innerHeight属性减去水平滚动条的高度(如果有的话)。document.body的高度则是网页的实际高度。一般来说,document.body.clientHeight大于document.documentElement.clientHeight。
// 视口高度
document.documentElement.clientHeight
// 网页总高度
document.body.clientHeightElement.clientLeft
Element.clientLeft属性等于元素节点左边框(left border)的宽度(单位像素),不包括左侧的padding和margin。如果没有设置左边框,或者是行内元素(display: inline),该属性返回0。该属性总是返回整数值,如果是小数,会四舍五入。
Element.clientTop
Element.clientTop属性等于网页元素顶部边框的宽度(单位像素),其他特点都与clientLeft相同。
Element.scrollHeight
Element.scrollHeight属性返回一个整数值(小数会四舍五入),表示当前元素的总高度(单位像素),包括溢出容器、当前不可见的部分。
它包括padding,但是不包括border、margin以及水平滚动条的高度(如果有水平滚动条的话),还包括伪元素(::before或::after)的高度。
Element.scrollWidth
Element.scrollWidth属性表示当前元素的总宽度(单位像素),其他地方都与scrollHeight属性类似。这两个属性只读。
整张网页的总高度可以从document.documentElement或document.body上读取。
// 返回网页的总高度
document.documentElement.scrollHeight
document.body.scrollHeight注意,如果元素节点的内容出现溢出,即使溢出的内容是隐藏的,scrollHeight属性仍然返回元素的总高度。
// HTML 代码如下
// <div id="myDiv" style="height: 200px; overflow: hidden;">...</div>
document.getElementById('myDiv').scrollHeight // 200上面代码中,即使myDiv元素的 CSS 高度只有200像素,且溢出部分不可见,但是scrollHeight仍然会返回该元素的原始高度。
Element.scrollLeft
Element.scrollLeft属性表示当前元素的水平滚动条向右侧滚动的像素数量。
Element.scrollTop
Element.scrollTop属性表示当前元素的垂直滚动条向下滚动的像素数量。
上述两个属性对于那些没有滚动条的网页元素,这两个属性总是等于0。
如果要查看整张网页的水平的和垂直的滚动距离,要从document.documentElement元素上读取。
document.documentElement.scrollLeft
document.documentElement.scrollTop这两个属性都可读写,设置该属性的值,会导致浏览器将当前元素自动滚动到相应的位置。
Element.offsetParent
Element.offsetParent属性返回最靠近当前元素的、并且 CSS 的position属性不等于static的上层元素。
<div style="position: absolute;">
<p>
<span>Hello</span>
</p>
</div>上面代码中,span元素的offsetParent属性就是div元素。
该属性主要用于确定子元素位置偏移的计算基准,Element.offsetTop和Element.offsetLeft就是offsetParent元素计算的。
如果该元素是不可见的(display属性为none),或者位置是固定的(position属性为fixed),则offsetParent属性返回null。
<div style="position: absolute;">
<p>
<span style="display: none;">Hello</span>
</p>
</div>上面代码中,span元素的offsetParent属性是null。
如果某个元素的所有上层节点的position属性都是static,则Element.offsetParent属性指向<body>元素。
Element.offsetHeight
Element.offsetHeight属性返回一个整数,表示元素的 CSS 垂直高度(单位像素),包括元素本身的高度、padding 和 border,以及水平滚动条的高度(如果存在滚动条)
Element.offsetWidth
Element.offsetWidth属性表示元素的 CSS 水平宽度(单位像素),其他都与Element.offsetHeight一致。
这两个属性都是只读属性,只比Element.clientHeight和Element.clientWidth多了边框的高度或宽度。如果元素的 CSS 设为不可见(比如display: none;),则返回0。
Element.offsetLeft
Element.offsetTop
Element.offsetLeft返回当前元素左上角相对于Element.offsetParent节点的水平位移,Element.offsetTop返回垂直位移,单位为像素。通常,这两个值是指相对于父节点的位移。
下面的代码可以算出元素左上角相对于整张网页的坐标。
function getElementPosition(e) {
var x = 0;
var y = 0;
while (e !== null) {
x += e.offsetLeft;
y += e.offsetTop;
e = e.offsetParent;
}
return {x: x, y: y};
}Element.style
每个元素节点都有style用来读写该元素的行内样式信息。
Element.children
Element.childElementCount
Element.children属性返回一个类似数组的对象(HTMLCollection实例),包括当前元素节点的所有子元素。如果当前元素没有子元素,则返回的对象包含零个成员。
这个属性与Node.childNodes属性的区别是,它只包括元素类型的子节点,不包括其他类型的子节点。
Element.childElementCount属性返回当前元素节点包含的子元素节点的个数,与Element.children.length的值相同。
Element.firstElementChild
Element.lastElementChild
Element.firstElementChild属性返回当前元素的第一个元素子节点,Element.lastElementChild返回最后一个元素子节点。
如果没有元素子节点,这两个属性返回null。
Element.nextElementSibling
Element.previousElementSibling
Element.nextElementSibling属性返回当前元素节点的后一个同级元素节点,如果没有则返回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属性返回当前元素节点的前一个同级元素节点,如果没有则返回null。
实例方法
属性相关
元素节点提供六个方法,用来操作属性。
getAttribute():读取某个属性的值getAttributeNames():返回当前元素的所有属性名setAttribute():写入属性值hasAttribute():某个属性是否存在hasAttributes():当前元素是否有属性removeAttribute():删除属性
Element.querySelector()
Element.querySelector方法接受 CSS 选择器作为参数,返回父元素的第一个匹配的子元素。如果没有找到匹配的子元素,就返回null。
var content = document.getElementById('content');
var el = content.querySelector('p');上面代码返回content节点的第一个p元素。
Element.querySelector方法可以接受任何复杂的 CSS 选择器。
注意,这个方法无法选中伪元素。
它可以接受多个选择器,它们之间使用逗号分隔。
element.querySelector('div, p')上面代码返回element的第一个div或p子元素。
需要注意的是,浏览器执行querySelector方法时,是先在全局范围内搜索给定的 CSS 选择器,然后过滤出哪些属于当前元素的子元素。因此,会有一些违反直觉的结果,下面是一段 HTML 代码。
<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>Element.querySelectorAll()
Element.querySelectorAll方法接受 CSS 选择器作为参数,返回一个NodeList实例,包含所有匹配的子元素。
var el = document.querySelector('#test');
var matches = el.querySelectorAll('div.highlighted > p');该方法的执行机制与querySelector方法相同,也是先在全局范围内查找,再过滤出当前元素的子元素。因此,选择器实际上针对整个文档的。
它也可以接受多个 CSS 选择器,它们之间使用逗号分隔。如果选择器里面有伪元素的选择器,则总是返回一个空的NodeList实例。
Element.getElementsByClassName()
Element.getElementsByClassName方法返回一个HTMLCollection实例,成员是当前元素节点的所有具有指定 class 的子元素节点。该方法与document.getElementsByClassName方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
element.getElementsByClassName('red test');注意,该方法的参数大小写敏感。
由于HTMLCollection实例是一个活的集合,document对象的任何变化会立刻反应到实例,下面的代码不会生效。
// HTML 代码如下
// <div id="example">
// <p class="foo"></p>
// <p class="foo"></p>
// </div>
var element = document.getElementById('example');
var matches = element.getElementsByClassName('foo');
for (var i = 0; i< matches.length; i++) {
matches[i].classList.remove('foo');
matches.item(i).classList.add('bar');
}
// 执行后,HTML 代码如下
// <div id="example">
// <p></p>
// <p class="foo bar"></p>
// </div>上面代码中,matches集合的第一个成员,一旦被拿掉 class 里面的foo,就会立刻从matches里面消失,导致出现上面的结果。
Element.getElementsByTagName()
Element.getElementsByTagName()方法返回一个HTMLCollection实例,成员是当前节点的所有匹配指定标签名的子元素节点。该方法与document.getElementsByClassName()方法的用法类似,只是搜索范围不是整个文档,而是当前元素节点。
var table = document.getElementById('forecast-table');
var cells = table.getElementsByTagName('td');注意,该方法的参数是大小写不敏感的,因为 HTML 标签名也是大小写不敏感。
Element.closest()
Element.closest方法接受一个 CSS 选择器作为参数,返回匹配该选择器的、最接近当前节点的一个祖先节点(包括当前节点本身)。如果没有任何节点匹配 CSS 选择器,则返回null。
Element.matches()
Element.matches方法返回一个布尔值,表示当前元素是否匹配给定的 CSS 选择器。
if (el.matches('.someClass')) {
console.log('Match!');
}事件相关
以下三个方法与Element节点的事件相关。这些方法都继承自EventTarget接口。
Element.addEventListener():添加事件的回调函数Element.removeEventListener():移除事件监听函数Element.dispatchEvent():触发事件
var event = new Event('click');
element.dispatchEvent(event);Element.scrollIntoView()
Element.scrollIntoView方法滚动当前元素,进入浏览器的可见区域,类似于设置window.location.hash的效果。
该方法可以接受一个布尔值作为参数。如果为true,表示元素的顶部与当前区域的可见部分的顶部对齐(前提是当前区域可滚动);
如果为false,表示元素的底部与当前区域的可见部分的尾部对齐(前提是当前区域可滚动)。如果没有提供该参数,默认为true。
Element.getBoundingClientRect()
Element.getBoundingClientRect方法返回一个对象,提供当前元素节点的大小、位置等信息,基本上就是 CSS 盒状模型的所有信息。
var rect = obj.getBoundingClientRect();上面代码中,getBoundingClientRect方法返回的rect对象,具有以下属性(全部为只读)。
x:元素左上角相对于视口的横坐标y:元素左上角相对于视口的纵坐标height:元素高度width:元素宽度left:元素左上角相对于视口的横坐标,与x属性相等right:元素右边界相对于视口的横坐标(等于x + width)top:元素顶部相对于视口的纵坐标,与y属性相等bottom:元素底部相对于视口的纵坐标(等于y + height)
由于元素相对于视口(viewport)的位置,会随着页面滚动变化,因此表示位置的四个属性值,都不是固定不变的。如果想得到绝对位置,可以将left属性加上window.scrollX,top属性加上window.scrollY。
注意,getBoundingClientRect方法的所有属性,都把边框(border属性)算作元素的一部分。也就是说,都是从边框外缘的各个点来计算。因此,width和height包括了元素本身 + padding + border。
另外,上面的这些属性,都是继承自原型的属性,Object.keys会返回一个空数组,这一点也需要注意。
var rect = document.body.getBoundingClientRect();
Object.keys(rect) // []上面代码中,rect对象没有自身属性,而Object.keys方法只返回对象自身的属性,所以返回了一个空数组。
Element.getClientRects()
Element.getClientRects方法返回一个类似数组的对象,里面是当前元素在页面上形成的所有矩形(所以方法名中的Rect用的是复数)。每个矩形都有bottom、height、left、right、top和width六个属性,表示它们相对于视口的四个坐标,以及本身的高度和宽度。
Element.insertAdjacentElement()
Element.insertAdjacentElement方法在相对于当前元素的指定位置,插入一个新的节点。该方法返回被插入的节点,如果插入失败,返回null。
element.insertAdjacentElement(position, element);Element.insertAdjacentElement方法一共可以接受两个参数,第一个参数是一个字符串,表示插入的位置,第二个参数是将要插入的节点。第一个参数只可以取如下的值。
beforebegin:当前元素之前afterbegin:当前元素内部的第一个子节点前面beforeend:当前元素内部的最后一个子节点后面afterend:当前元素之后
注意,beforebegin和afterend这两个值,只在当前节点有父节点时才会生效。如果当前节点是由脚本创建的,没有父节点,那么插入会失败。
如果插入的节点是一个文档里现有的节点,它会从原有位置删除,放置到新的位置。
Element.insertAdjacentHTML()
Element.insertAdjacentText()
Element.insertAdjacentHTML方法用于将一个 HTML 字符串,解析生成 DOM 结构,插入相对于当前节点的指定位置。
element.insertAdjacentHTML(position, text);该方法接受两个参数,第一个是一个表示指定位置的字符串,第二个是待解析的 HTML 字符串。第一个参数只能设置下面四个值之一。
beforebegin:当前元素之前afterbegin:当前元素内部的第一个子节点前面beforeend:当前元素内部的最后一个子节点后面afterend:当前元素之后
// HTML 代码:<div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// 执行后的 HTML 代码:
// <div id="one">one</div><div id="two">two</div>该方法只是在现有的 DOM 结构里面插入节点,这使得它的执行速度比innerHTML方法快得多。
注意,该方法不会转义 HTML 字符串,这导致它不能用来插入用户输入的内容,否则会有安全风险。
Element.insertAdjacentText方法在相对于当前节点的指定位置,插入一个文本节点,用法与Element.insertAdjacentHTML方法完全一致。
// HTML 代码:<div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentText('afterend', 'two');
// 执行后的 HTML 代码:
// <div id="one">one</div>twoElement.remove()
Element.remove方法继承自 ChildNode 接口,用于将当前元素节点从它的父节点移除。
var el = document.getElementById('mydiv');
el.remove();上面代码将el节点从 DOM 树里面移除。
Element.focus()
Element.blur()
Element.focus方法用于将当前页面的焦点,转移到指定元素上。
document.getElementById('my-span').focus();该方法可以接受一个对象作为参数。参数对象的preventScroll属性是一个布尔值,指定是否将当前元素停留在原始位置,而不是滚动到可见区域。
function getFocus() {
document.getElementById('btn').focus({preventScroll:false});
}上面代码会让btn元素获得焦点,并滚动到可见区域。
最后,从document.activeElement属性可以得到当前获得焦点的元素。
Element.blur方法用于将焦点从当前元素移除。
Element.click()
Element.click方法用于在当前元素上模拟一次鼠标点击,相当于触发了click事件。
属性操作
HTML 元素包括标签名和若干个键值对,这个键值对就称为“属性”(attribute)。
<a id="test" href="http://www.example.com">
链接
</a>上面代码中,a元素包括两个属性:id属性和href属性。
属性本身是一个对象(Attr对象),但是实际上,这个对象极少使用。一般都是通过元素节点对象(HTMlElement对象)来操作属性。
Element.attributes 属性
元素对象有一个attributes属性,返回一个类似数组的动态对象,成员是该元素标签的所有属性节点对象,属性的实时变化都会反映在这个节点对象上。
其他类型的节点对象,虽然也有attributes属性,但返回的都是null,因此可以把这个属性视为元素对象独有的。
单个属性可以通过序号引用,也可以通过属性名引用。
// HTML 代码如下
// <body bgcolor="yellow" onload="">
document.body.attributes[0]
document.body.attributes.bgcolor
document.body.attributes['ONLOAD']注意,上面代码的三种方法,返回的都是属性节点对象,而不是属性值。
属性节点对象有name和value属性,对应该属性的属性名和属性值,等同于nodeName属性和nodeValue属性。
// HTML代码为
// <div id="mydiv">
var n = document.getElementById('mydiv');
n.attributes[0].name // "id"
n.attributes[0].nodeName // "id"
n.attributes[0].value // "mydiv"
n.attributes[0].nodeValue // "mydiv"下面代码可以遍历一个元素节点的所有属性。
var para = document.getElementsByTagName('p')[0];
var result = document.getElementById('result');
if (para.hasAttributes()) {
var attrs = para.attributes;
var output = '';
for(var i = attrs.length - 1; i >= 0; i--) {
output += attrs[i].name + '->' + attrs[i].value;
}
result.textContent = output;
} else {
result.textContent = 'No attributes to show';
}元素的标准属性
HTML 元素的标准属性(即在标准中定义的属性),会自动成为元素节点对象的属性。
var a = document.getElementById('test');
a.id // "test"
a.href // "http://www.example.com/"上面代码中,a元素标签的属性id和href,自动成为节点对象的属性。
这些属性都是可写的。
var img = document.getElementById('myImage');
img.src = 'http://www.example.com/image.jpg';上面的写法,会立刻替换掉img对象的src属性,即会显示另外一张图片。
这种修改属性的方法,常常用于添加表单的属性。
var f = document.forms[0];
f.action = 'submit.php';
f.method = 'POST';上面代码为表单添加提交网址和提交方法。
注意,这种用法虽然可以读写属性,但是无法删除属性,delete运算符在这里不会生效。
HTML 元素的属性名是大小写不敏感的,但是 JavaScript 对象的属性名是大小写敏感的。转换规则是,转为 JavaScript 属性名时,一律采用小写。如果属性名包括多个单词,则采用骆驼拼写法,即从第二个单词开始,每个单词的首字母采用大写,比如onClick。
有些 HTML 属性名是 JavaScript 的保留字,转为 JavaScript 属性时,必须改名。主要是以下两个。
for属性改为htmlForclass属性改为className
另外,HTML 属性值一般都是字符串,但是 JavaScript 属性会自动转换类型。比如,将字符串true转为布尔值,将onClick的值转为一个函数,将style属性的值转为一个CSSStyleDeclaration对象。因此,可以对这些属性赋予各种类型的值。
属性操作的标准方法
概述
元素节点提供六个方法,用来操作属性。
getAttribute()getAttributeNames()setAttribute()hasAttribute()hasAttributes()removeAttribute()
这有几点注意。
(1)适用性
这六个方法对所有属性(包括用户自定义的属性)都适用。
(2)返回值
getAttribute()只返回字符串,不会返回其他类型的值。
(3)属性名
这些方法只接受属性的标准名称,不用改写保留字,比如for和class都可以直接使用。另外,这些方法对于属性名是大小写不敏感的。
var image = document.images[0];
image.setAttribute('class', 'myImage');上面代码中,setAttribute方法直接使用class作为属性名,不用写成className。
Element.getAttribute()
Element.getAttribute方法返回当前元素节点的指定属性。如果指定属性不存在,则返回null。
// HTML 代码为
// <div id="div1" align="left">
var div = document.getElementById('div1');
div.getAttribute('align') // "left"Element.getAttributeNames()
Element.getAttributeNames()返回一个数组,成员是当前元素的所有属性的名字。如果当前元素没有任何属性,则返回一个空数组。
使用Element.attributes属性,也可以拿到同样的结果,唯一的区别是它返回的是类似数组的对象。
var mydiv = document.getElementById('mydiv');
mydiv.getAttributeNames().forEach(function (key) {
var value = mydiv.getAttribute(key);
console.log(key, value);
})上面代码用于遍历某个节点的所有属性。
Element.setAttribute()
Element.setAttribute方法用于为当前元素节点新增属性。如果同名属性已存在,则相当于编辑已存在的属性。该方法没有返回值。
// HTML 代码为
// <button>Hello World</button>
var b = document.querySelector('button');
b.setAttribute('name', 'myButton');
b.setAttribute('disabled', true);上面代码中,button元素的name属性被设成myButton,disabled属性被设成true。
这里有两个地方需要注意,首先,属性值总是字符串,其他类型的值会自动转成字符串,比如布尔值true就会变成字符串true;
其次,上例的disable属性是一个布尔属性,对于<button>元素来说,这个属性不需要属性值,只要设置了就总是会生效,因此setAttribute方法里面可以将disabled属性设成任意值。
Element.hasAttribute()
Element.hasAttribute方法返回一个布尔值,表示当前元素节点是否包含指定属性。
var d = document.getElementById('div1');
if (d.hasAttribute('align')) {
d.setAttribute('align', 'center');
}上面代码检查div节点是否含有align属性。如果有,则设置为居中对齐。
Element.hasAttributes()
Element.hasAttributes方法返回一个布尔值,表示当前元素是否有属性,如果没有任何属性,就返回false,否则返回true。
var foo = document.getElementById('foo');
foo.hasAttributes() // trueElement.removeAttribute()
Element.removeAttribute方法移除指定属性。该方法没有返回值。
// HTML 代码为
// <div id="div1" align="left" width="200px">
document.getElementById('div1').removeAttribute('align');
// 现在的HTML代码为
// <div id="div1" width="200px">dataset 属性
有时,需要在HTML元素上附加数据,供 JavaScript 脚本使用。一种解决方法是自定义属性。
<div id="mydiv" foo="bar">上面代码为div元素自定义了foo属性,然后可以用getAttribute()和setAttribute()读写这个属性。
var n = document.getElementById('mydiv');
n.getAttribute('foo') // bar
n.setAttribute('foo', 'baz')这种方法虽然可以达到目的,但是会使得 HTML 元素的属性不符合标准,导致网页代码通不过校验。
更好的解决方法是,使用标准提供的data-*属性。
<div id="mydiv" data-foo="bar">然后,使用元素节点对象的dataset属性,它指向一个对象,可以用来操作 HTML 元素标签的data-*属性。
var n = document.getElementById('mydiv');
n.dataset.foo // bar
n.dataset.foo = 'baz'上面代码中,通过dataset.foo读写data-foo属性。
删除一个data-*属性,可以直接使用delete命令。
delete document.getElementById('myDiv').dataset.foo;除了dataset属性,也可以用getAttribute('data-foo')、removeAttribute('data-foo')、setAttribute('data-foo')、hasAttribute('data-foo')等方法操作data-*属性。
注意,data-后面的属性名有限制,只能包含字母、数字、连词线(-)、点(.)、冒号(:)和下划线(_)。
而且,属性名不应该使用A到Z的大写字母,比如不能有data-helloWorld这样的属性名,而要写成data-hello-world。
转成dataset的键名时,连词线后面如果跟着一个小写字母,那么连词线会被移除,该小写字母转为大写字母,其他字符不变。
反过来,dataset的键名转成属性名时,所有大写字母都会被转成连词线+该字母的小写形式,其他字符不变。
比如,dataset.helloWorld会转成data-hello-world。
Text 节点
概念
文本节点(Text)代表元素节点(Element)和属性节点(Attribute)的文本内容。
如果一个节点只包含一段文本,那么它就有一个文本子节点,代表该节点的文本内容。
通常我们使用父节点的firstChild、nextSibling等属性获取文本节点,或者使用Document节点的createTextNode方法创造一个文本节点。
// 获取文本节点
var textNode = document.querySelector('p').firstChild;
// 创造文本节点
var textNode = document.createTextNode('Hi');
document.querySelector('div').appendChild(textNode);浏览器原生提供一个Text构造函数。它返回一个文本节点实例。它的参数就是该文本节点的文本内容。
// 空字符串
var text1 = new Text();
// 非空字符串
var text2 = new Text('This is a text node');注意,由于空格也是一个字符,所以哪怕只有一个空格,也会形成文本节点。比如,<p> </p>包含一个空格,它的子节点就是一个文本节点。
文本节点除了继承Node接口,还继承了CharacterData接口。
属性
data
data属性等同于nodeValue属性,用来设置或读取文本节点的内容。
// 读取文本内容
document.querySelector('p').firstChild.data
// 等同于
document.querySelector('p').firstChild.nodeValue
// 设置文本内容
document.querySelector('p').firstChild.data = 'Hello World';wholeText
wholeText属性将当前文本节点与毗邻的文本节点,作为一个整体返回。大多数情况下,wholeText属性的返回值,与data属性和textContent属性相同。但是,某些特殊情况会有差异。
举例来说,HTML 代码如下。
<p id="para">A <em>B</em> C</p>这时,文本节点的wholeText属性和data属性,返回值相同。
var el = document.getElementById('para');
el.firstChild.wholeText // "A "
el.firstChild.data // "A "但是,一旦移除<em>节点,wholeText属性与data属性就会有差异,因为这时其实<p>节点下面包含了两个毗邻的文本节点。
el.removeChild(para.childNodes[1]);
el.firstChild.wholeText // "A C"
el.firstChild.data // "A "length
length属性返回当前文本节点的文本长度。
(new Text('Hello')).length // 5nextElementSibling
previousElementSibling
nextElementSibling属性返回紧跟在当前文本节点后面的那个同级元素节点。如果取不到元素节点,则返回null。
// HTML 为
// <div>Hello <em>World</em></div>
var tn = document.querySelector('div').firstChild;
tn.nextElementSibling
// <em>World</em>previousElementSibling属性返回当前文本节点前面最近的同级元素节点。如果取不到元素节点,则返回null:。
方法
appendData()
deleteData()
insertData()
replaceData()
subStringData()
以下5个方法都是编辑Text节点文本内容的方法
appendData():在Text节点尾部追加字符串。deleteData():删除Text节点内部的子字符串,第一个参数为子字符串开始位置,第二个参数为子字符串长度。insertData():在Text节点插入字符串,第一个参数为插入位置,第二个参数为插入的子字符串。replaceData():用于替换文本,第一个参数为替换开始位置,第二个参数为需要被替换掉的长度,第三个参数为新加入的字符串。subStringData():用于获取子字符串,第一个参数为子字符串在Text节点中的开始位置,第二个参数为子字符串长度。
// HTML 代码为
// <p>Hello World</p>
var pElementText = document.querySelector('p').firstChild;
pElementText.appendData('!');
// 页面显示 Hello World!
pElementText.deleteData(7, 5);
// 页面显示 Hello W
pElementText.insertData(7, 'Hello ');
// 页面显示 Hello WHello
pElementText.replaceData(7, 5, 'World');
// 页面显示 Hello WWorld
pElementText.substringData(7, 10);
// 页面显示不变,返回"World "remove()
remove方法用于移除当前Text节点。
// HTML 代码为
// <p>Hello World</p>
document.querySelector('p').firstChild.remove()
// 现在 HTML 代码为
// <p></p>splitText()
splitText方法将Text节点一分为二,变成两个毗邻的Text节点。
它的参数就是分割位置(从零开始),分割到该位置的字符前结束。如果分割位置不存在,将报错。
分割后,该方法返回分割位置后方的字符串,而原Text节点变成只包含分割位置前方的字符串。
// html 代码为 <p id="p">foobar</p>
var p = document.getElementById('p');
var textnode = p.firstChild;
var newText = textnode.splitText(3);
newText // "bar"
textnode // "foo"父元素节点的normalize方法可以将毗邻的两个Text节点合并。
接上面的例子,文本节点的splitText方法将一个Text节点分割成两个,父元素的normalize方法可以实现逆操作,将它们合并。
p.childNodes.length // 2
// 将毗邻的两个 Text 节点合并
p.normalize();
p.childNodes.length // 1DocumentFragment 节点
DocumentFragment节点代表一个文档的片段,本身就是一个完整的 DOM 树形结构。
它没有父节点,parentNode返回null,但是可以插入任意数量的子节点。
它不属于当前文档,操作DocumentFragment节点,要比直接操作 DOM 树快得多。
它一般用于构建一个 DOM 结构,然后插入当前文档。
document.createDocumentFragment方法,以及浏览器原生的DocumentFragment构造函数,可以创建一个空的DocumentFragment节点。然后再使用其他 DOM 方法,向其添加子节点。
var docFrag = document.createDocumentFragment();
// 等同于
var docFrag = new DocumentFragment();
var li = document.createElement('li');
li.textContent = 'Hello World';
docFrag.appendChild(li);
document.querySelector('ul').appendChild(docFrag);上面代码创建了一个DocumentFragment节点,然后将一个li节点添加在它里面,最后将DocumentFragment节点移动到原文档。
注意,DocumentFragment节点本身不能被插入当前文档。当它作为appendChild()、insertBefore()、replaceChild()等方法的参数时,是它的所有子节点插入当前文档,而不是它自身。一旦DocumentFragment节点被添加进当前文档,它自身就变成了空节点(textContent属性为空字符串),可以被再次使用。
如果想要保存DocumentFragment节点的内容,可以使用cloneNode方法。
document
.querySelector('ul')
.appendChild(docFrag.cloneNode(true));上面这样添加DocumentFragment节点进入当前文档,不会清空DocumentFragment节点。
下面是一个例子,使用DocumentFragment反转一个指定节点的所有子节点的顺序。
function reverse(n) {
var f = document.createDocumentFragment();
while(n.lastChild) f.appendChild(n.lastChild);
n.appendChild(f);
}DocumentFragment节点对象没有自己的属性和方法,全部继承自Node节点和ParentNode接口。也就是说,DocumentFragment节点比Node节点多出以下四个属性。
children:返回一个动态的HTMLCollection集合对象,包括当前DocumentFragment对象的所有子元素节点。firstElementChild:返回当前DocumentFragment对象的第一个子元素节点,如果没有则返回null。lastElementChild:返回当前DocumentFragment对象的最后一个子元素节点,如果没有则返回null。childElementCount:返回当前DocumentFragment对象的所有子元素数量。
CSS 操作
CSS 与 JavaScript 是两个有着明确分工的领域,前者负责页面的视觉效果,后者负责与用户的行为互动。但是,它们毕竟同属网页开发的前端,因此不可避免有着交叉和互相配合。
HTML 元素的 style 属性
操作 CSS 样式最简单的方法,就是使用网页元素节点的getAttribute()方法、setAttribute()方法和removeAttribute()方法,直接读写或删除网页元素的style属性。
div.setAttribute(
'style',
'background-color:red;' + 'border:1px solid black;'
);上面的代码相当于下面的 HTML 代码。
<div style="background-color:red; border:1px solid black;" />CSSStyleDeclaration 接口
简介
CSSStyleDeclaration 接口用来操作元素的样式。三个地方部署了这个接口。
- 元素节点的
style属性(Element.style) CSSStyle实例的style属性window.getComputedStyle()的返回值
CSSStyleDeclaration 接口可以直接读写 CSS 的样式属性,不过,连词号需要变成骆驼拼写法。
var divStyle = document.querySelector('div').style;
divStyle.backgroundColor = 'red';
divStyle.border = '1px solid black';
divStyle.width = '100px';
divStyle.height = '100px';
divStyle.fontSize = '10em';
divStyle.backgroundColor // red
divStyle.border // 1px solid black
divStyle.height // 100px
divStyle.width // 100px上面代码中,style属性的值是一个 CSSStyleDeclaration 实例。
这个对象所包含的属性与 CSS 规则一一对应,但是名字需要改写,比如background-color写成backgroundColor。
改写的规则是将横杠从 CSS 属性名中去除,然后将横杠后的第一个字母大写。如果 CSS 属性名是 JavaScript 保留字,则规则名之前需要加上字符串css,比如float写成cssFloat。
注意,该对象的属性值都是字符串,设置时必须包括单位,但是不含规则结尾的分号。比如,divStyle.width不能写为100,而要写为100px。
另外,Element.style返回的只是行内样式,并不是该元素的全部样式。
通过样式表设置的样式,或者从父元素继承的样式,无法通过这个属性得到。元素的全部样式要通过window.getComputedStyle()得到。
实例属性
(1)CSSStyleDeclaration.cssText
CSSStyleDeclaration.cssText属性用来读写当前规则的所有样式声明文本。
var divStyle = document.querySelector('div').style;
divStyle.cssText = 'background-color: red;'
+ 'border: 1px solid black;'
+ 'height: 100px;'
+ 'width: 100px;';注意,cssText的属性值不用改写 CSS 属性名。
删除一个元素的所有行内样式,最简便的方法就是设置cssText为空字符串。
divStyle.cssText = '';(2)CSSStyleDeclaration.length
CSSStyleDeclaration.length属性返回一个整数值,表示当前规则包含多少条样式声明。
// HTML 代码如下
// <div id="myDiv"
// style="height: 1px;width: 100%;background-color: #CA1;"
// ></div>
var myDiv = document.getElementById('myDiv');
var divStyle = myDiv.style;
divStyle.length // 3(3)CSSStyleDeclaration.parentRule
CSSStyleDeclaration.parentRule属性返回当前规则所属的那个样式块(CSSRule 实例)。如果不存在所属的样式块,该属性返回null。
该属性只读,且只在使用 CSSRule 接口时有意义。
实例方法
(1)CSSStyleDeclaration.getPropertyPriority()
CSSStyleDeclaration.getPropertyPriority方法接受 CSS 样式的属性名作为参数,返回一个字符串,表示有没有设置important优先级。如果有就返回important,否则返回空字符串。
// HTML 代码为
// <div id="myDiv" style="margin: 10px!important; color: red;"/>
var style = document.getElementById('myDiv').style;
style.margin // "10px"
style.getPropertyPriority('margin') // "important"
style.getPropertyPriority('color') // ""(2)CSSStyleDeclaration.getPropertyValue()
CSSStyleDeclaration.getPropertyValue方法接受 CSS 样式属性名作为参数,返回一个字符串,表示该属性的属性值。
// HTML 代码为
// <div id="myDiv" style="margin: 10px!important; color: red;"/>
var style = document.getElementById('myDiv').style;
style.margin // "10px"
style.getPropertyValue("margin") // "10px"(3)CSSStyleDeclaration.item()
CSSStyleDeclaration.item方法接受一个整数值作为参数,返回该位置的 CSS 属性名。
// HTML 代码为
// <div id="myDiv" style="color: red; background-color: white;"/>
var style = document.getElementById('myDiv').style;
style.item(0) // "color"
style.item(1) // "background-color"(4)CSSStyleDeclaration.removeProperty()
CSSStyleDeclaration.removeProperty方法接受一个属性名作为参数,在 CSS 规则里面移除这个属性,返回这个属性原来的值。
// HTML 代码为
// <div id="myDiv" style="color: red; background-color: white;">
// 111
// </div>
var style = document.getElementById('myDiv').style;
style.removeProperty('color') // 'red'
// HTML 代码变为
// <div id="myDiv" style="background-color: white;">(5)CSSStyleDeclaration.setProperty()
CSSStyleDeclaration.setProperty方法用来设置新的 CSS 属性。该方法没有返回值。
该方法可以接受三个参数。
- 第一个参数:属性名,该参数是必需的。
- 第二个参数:属性值,该参数可选。如果省略,则参数值默认为空字符串。
- 第三个参数:优先级,该参数可选。如果设置,唯一的合法值是
important,表示 CSS 规则里面的!important。
// HTML 代码为
// <div id="myDiv" style="color: red; background-color: white;">
// 111
// </div>
var style = document.getElementById('myDiv').style;
style.setProperty('border', '1px solid blue');CSS 模块的侦测
CSS 的规格发展太快,新的模块层出不穷。不同浏览器的不同版本,对 CSS 模块的支持情况都不一样。有时候,需要知道当前浏览器是否支持某个模块,这就叫做“CSS模块的侦测”。
一个比较普遍适用的方法是,判断元素的style对象的某个属性值是否为字符串。
typeof element.style.animationName === 'string';
typeof element.style.transform === 'string';如果该 CSS 属性确实存在,会返回一个字符串。即使该属性实际上并未设置,也会返回一个空字符串。如果该属性不存在,则会返回undefined。
document.body.style['maxWidth'] // ""
document.body.style['maximumWidth'] // undefined另外,使用的时候,需要把不同浏览器的 CSS 前缀也考虑进去。
var content = document.getElementById('content');
typeof content.style['webkitAnimation'] === 'string'封装函数
function isPropertySupported(property) {
if (property in document.body.style) return true;
var prefixes = ['Moz', 'Webkit', 'O', 'ms', 'Khtml'];
var prefProperty = property.charAt(0).toUpperCase() + property.substr(1);
for(var i = 0; i < prefixes.length; i++){
if((prefixes[i] + prefProperty) in document.body.style) return true;
}
return false;
}
isPropertySupported('background-clip')
// trueCSS 对象
浏览器原生提供 CSS 对象,为 JavaScript 操作 CSS 提供一些工具方法。
这个对象目前有两个静态方法。
CSS.escape()
CSS.escape方法用于转义 CSS 选择器里面的特殊字符。
<div id="foo#bar">上面代码中,该元素的id属性包含一个#号,该字符在 CSS 选择器里面有特殊含义。不能直接写成document.querySelector('#foo#bar'),只能写成document.querySelector('#foo\\#bar')。这里必须使用双斜杠的原因是,单引号字符串本身会转义一次斜杠。
CSS.escape方法就用来转义那些特殊字符。
document.querySelector('#' + CSS.escape('foo#bar'))CSS.supports()
CSS.supports方法返回一个布尔值,表示当前环境是否支持某一句 CSS 规则。
它的参数有两种写法,一种是第一个参数是属性名,第二个参数是属性值;另一种是整个参数就是一行完整的 CSS 语句。
// 第一种写法
CSS.supports('transform-origin', '5px') // true
// 第二种写法
CSS.supports('display: table-cell') // true注意,第二种写法的参数结尾不能带有分号,否则结果不准确。
CSS.supports('display: table-cell;') // falsewindow.getComputedStyle()
行内样式(inline style)具有最高的优先级,改变行内样式,通常会立即反映出来。
但是,网页元素最终的样式是综合各种规则计算出来的。因此,如果想得到元素实际的样式,只读取行内样式是不够的,需要得到浏览器最终计算出来的样式规则。
window.getComputedStyle()方法,就用来返回浏览器计算后得到的最终规则。
它接受一个节点对象作为参数,返回一个 CSSStyleDeclaration 实例,包含了指定节点的最终样式信息。所谓“最终样式信息”,指的是各种 CSS 规则叠加后的结果。
var div = document.querySelector('div');
var styleObj = window.getComputedStyle(div);
styleObj.backgroundColor上面代码中,得到的背景色就是div元素真正的背景色。
注意,CSSStyleDeclaration 实例是一个活的对象,任何对于样式的修改,会实时反映到这个实例上面。另外,这个实例是只读的。
getComputedStyle方法还可以接受第二个参数,表示当前元素的伪元素(比如:before、:after、:first-line、:first-letter等)。
var result = window.getComputedStyle(div, ':before');下面的例子是如何获取元素的高度。
var elem = document.getElementById('elem-container');
var styleObj = window.getComputedStyle(elem, null)
var height = styleObj.height;
// 等同于
var height = styleObj['height'];
var height = styleObj.getPropertyValue('height');上面代码得到的height属性,是浏览器最终渲染出来的高度,比其他方法得到的高度更可靠。
由于styleObj是 CSSStyleDeclaration 实例,所以可以使用各种 CSSStyleDeclaration 的实例属性和方法。
有几点需要注意。
- CSSStyleDeclaration 实例返回的 CSS 值都是绝对单位。比如,长度都是像素单位(返回值包括
px后缀),颜色是rgb(#, #, #)或rgba(#, #, #, #)格式。 - CSS 规则的简写形式无效。比如,想读取
margin属性的值,不能直接读,只能读marginLeft、marginTop等属性;再比如,font属性也是不能直接读的,只能读font-size等单个属性。 - 如果读取 CSS 原始的属性名,要用方括号运算符,比如
styleObj['z-index'];如果读取骆驼拼写法的 CSS 属性名,可以直接读取styleObj.zIndex。 - 该方法返回的 CSSStyleDeclaration 实例的
cssText属性总是返回空字符串。
CSS 伪元素
CSS 伪元素是通过 CSS 向 DOM 添加的元素,主要是通过:before和:after选择器生成,然后用content属性指定伪元素的内容。
<div id="test">Test content</div>#test:before {
content: 'Before ';
color: #FF0;
}节点元素的style对象无法读写伪元素的样式,这时就要用到window.getComputedStyle()。JavaScript 获取伪元素,可以使用下面的方法。
var test = document.querySelector('#test');
var result = window.getComputedStyle(test, ':before').content;
var color = window.getComputedStyle(test, ':before').color;此外,也可以使用 CSSStyleDeclaration 实例的getPropertyValue方法,获取伪元素的属性
var result = window.getComputedStyle(test, ':before')
.getPropertyValue('content');
var color = window.getComputedStyle(test, ':before')
.getPropertyValue('color');StyleSheet 接口
概述
StyleSheet接口代表网页的一张样式表,包括<link>元素加载的样式表和<style>元素内嵌的样式表。
document对象的styleSheets属性,可以返回当前页面的所有StyleSheet实例(即所有样式表)。它是一个类似数组的对象。
var sheets = document.styleSheets;
var sheet = document.styleSheets[0];
sheet instanceof StyleSheet // true如果是<style>元素嵌入的样式表,还有另一种获取StyleSheet实例的方法,就是这个节点元素的sheet属性。
// HTML 代码为 <style id="myStyle"></style>
var myStyleSheet = document.getElementById('myStyle').sheet;
myStyleSheet instanceof StyleSheet // true严格地说,StyleSheet接口不仅包括网页样式表,还包括 XML 文档的样式表。
所以,它有一个子类CSSStyleSheet表示网页的 CSS 样式表。我们在网页里面拿到的样式表实例,实际上是CSSStyleSheet的实例。
这个子接口继承了StyleSheet的所有属性和方法,并且定义了几个自己的属性,下面把这两个接口放在一起介绍。
实例属性
StyleSheet实例有以下属性。
(1)StyleSheet.disabled
StyleSheet.disabled返回一个布尔值,表示该样式表是否处于禁用状态。手动设置disabled属性为true,等同于在<link>元素里面,将这张样式表设为alternate stylesheet,即该样式表将不会生效。
(2)StyleSheet.href
StyleSheet.href返回样式表的网址。对于内嵌样式表,该属性返回null。该属性只读。
document.styleSheets[0].href(3)StyleSheet.media
StyleSheet.media属性返回一个类似数组的对象(MediaList实例),成员是表示适用媒介的字符串。
表示当前样式表是用于屏幕(screen),还是用于打印(print)或手持设备(handheld),或各种媒介都适用(all)。该属性只读,默认值是screen。
document.styleSheets[0].media.mediaText
// "all"MediaList实例的appendMedium方法,用于增加媒介;deleteMedium方法用于删除媒介。
document.styleSheets[0].media.appendMedium('handheld');
document.styleSheets[0].media.deleteMedium('print');(4)StyleSheet.title
StyleSheet.title属性返回样式表的title属性。
(5)StyleSheet.type
StyleSheet.type属性返回样式表的type属性,通常是text/css。
document.styleSheets[0].type // "text/css"(6)StyleSheet.parentStyleSheet
CSS 的@import命令允许在样式表中加载其他样式表。StyleSheet.parentStyleSheet属性返回包含了当前样式表的那张样式表。如果当前样式表是顶层样式表,则该属性返回null。
if (stylesheet.parentStyleSheet) {
sheet = stylesheet.parentStyleSheet;
} else {
sheet = stylesheet;
}(7)StyleSheet.ownerNode
StyleSheet.ownerNode属性返回StyleSheet对象所在的 DOM 节点,通常是<link>或<style>。对于那些由其他样式表引用的样式表,该属性为null。
// HTML代码为
// <link rel="StyleSheet" href="example.css" type="text/css" />
document.styleSheets[0].ownerNode
// <link rel="stylesheet" href="xxx.css">(8)CSSStyleSheet.cssRules
CSSStyleSheet.cssRules属性指向一个类似数组的对象(CSSRuleList实例),里面每一个成员就是当前样式表的一条 CSS 规则。使用该规则的cssText属性,可以得到 CSS 规则对应的字符串。
var sheet = document.querySelector('#styleElement').sheet;
sheet.cssRules[0].cssText
// "body { background-color: red; margin: 20px; }"
sheet.cssRules[1].cssText
// "p { line-height: 1.4em; color: blue; }"每条 CSS 规则还有一个style属性,指向一个对象,用来读写具体的 CSS 命令。
cssStyleSheet.cssRules[0].style.color = 'red';
cssStyleSheet.cssRules[1].style.color = 'purple';(9)CSSStyleSheet.ownerRule
有些样式表是通过@import规则输入的,它的ownerRule属性会返回一个CSSRule实例,代表那行@import规则。如果当前样式表不是通过@import引入的,ownerRule属性返回null。
实例方法
(1)CSSStyleSheet.insertRule()
CSSStyleSheet.insertRule方法用于在当前样式表的插入一个新的 CSS 规则。
var sheet = document.querySelector('#styleElement').sheet;
sheet.insertRule('#block { color: white }', 0);
sheet.insertRule('p { color: red }', 1);该方法可以接受两个参数,第一个参数是表示 CSS 规则的字符串,这里只能有一条规则,否则会报错。第二个参数是该规则在样式表的插入位置(从0开始),该参数可选,默认为0(即默认插在样式表的头部)。注意,如果插入位置大于现有规则的数目,会报错。
该方法的返回值是新插入规则的位置序号。
注意,浏览器对脚本在样式表里面插入规则有很多限制。所以,这个方法最好放在try...catch里使用。
(2)CSSStyleSheet.deleteRule()
CSSStyleSheet.deleteRule方法用来在样式表里面移除一条规则,它的参数是该条规则在cssRules对象中的位置。该方法没有返回值。
document.styleSheets[0].deleteRule(1);实例:添加样式表
网页添加样式表有两种方式。一种是添加一张内置样式表,即在文档中添加一个<style>节点。
// 写法一
var style = document.createElement('style');
style.setAttribute('media', 'screen');
style.innerHTML = 'body{color:red}';
document.head.appendChild(style);
// 写法二
var style = (function () {
var style = document.createElement('style');
document.head.appendChild(style);
return style;
})();
style.sheet.insertRule('.foo{color:red;}', 0);另一种是添加外部样式表,即在文档中添加一个<link>节点,然后将href属性指向外部样式表的 URL。
var linkElm = document.createElement('link');
linkElm.setAttribute('rel', 'stylesheet');
linkElm.setAttribute('type', 'text/css');
linkElm.setAttribute('href', 'reset-min.css');
document.head.appendChild(linkElm);CSSRuleList 接口
CSSRuleList 接口是一个类似数组的对象,表示一组 CSS 规则,成员都是 CSSRule 实例。
获取 CSSRuleList 实例,一般是通过StyleSheet.cssRules属性。
// HTML 代码如下
// <style id="myStyle">
// h1 { color: red; }
// p { color: blue; }
// </style>
var myStyleSheet = document.getElementById('myStyle').sheet;
var crl = myStyleSheet.cssRules;
crl instanceof CSSRuleList // trueCSSRuleList 实例里面,每一条规则(CSSRule 实例)可以通过rules.item(index)或者rules[index]拿到。CSS 规则的条数通过rules.length拿到。还是用上面的例子。
crl[0] instanceof CSSRule // true
crl.length // 2注意,添加规则和删除规则不能在 CSSRuleList 实例操作,而要在它的父元素 StyleSheet 实例上,通过StyleSheet.insertRule()和StyleSheet.deleteRule()操作。
CSSRule 接口
概述
一条 CSS 规则包括两个部分:CSS 选择器和样式声明。下面就是一条典型的 CSS 规则。
.myClass {
color: red;
background-color: yellow;
}JavaScript 通过 CSSRule 接口操作 CSS 规则。一般通过 CSSRuleList 接口(StyleSheet.cssRules)获取 CSSRule 实例。
// HTML 代码如下
// <style id="myStyle">
// .myClass {
// color: red;
// background-color: yellow;
// }
// </style>
var myStyleSheet = document.getElementById('myStyle').sheet;
var ruleList = myStyleSheet.cssRules;
var rule = ruleList[0];
rule instanceof CSSRule // trueCSSRule 实例的属性
(1)CSSRule.cssText
CSSRule.cssText属性返回当前规则的文本,还是使用上面的例子。
rule.cssText
// ".myClass { color: red; background-color: yellow; }"如果规则是加载(@import)其他样式表,cssText属性返回@import 'url'。
(2)CSSRule.parentStyleSheet
CSSRule.parentStyleSheet属性返回当前规则所在的样式表对象(StyleSheet 实例),还是使用上面的例子。
rule.parentStyleSheet === myStyleSheet // true(3)CSSRule.parentRule
CSSRule.parentRule属性返回包含当前规则的父规则,如果不存在父规则(即当前规则是顶层规则),则返回null。
父规则最常见的情况是,当前规则包含在@media规则代码块之中。
// HTML 代码如下
// <style id="myStyle">
// @supports (display: flex) {
// @media screen and (min-width: 900px) {
// article {
// display: flex;
// }
// }
// }
// </style>
var myStyleSheet = document.getElementById('myStyle').sheet;
var ruleList = myStyleSheet.cssRules;
var rule0 = ruleList[0];
rule0.cssText
// "@supports (display: flex) {
// @media screen and (min-width: 900px) {
// article { display: flex; }
// }
// }"
// 由于这条规则内嵌其他规则,
// 所以它有 cssRules 属性,且该属性是 CSSRuleList 实例
rule0.cssRules instanceof CSSRuleList // true
var rule1 = rule0.cssRules[0];
rule1.cssText
// "@media screen and (min-width: 900px) {
// article { display: flex; }
// }"
var rule2 = rule1.cssRules[0];
rule2.cssText
// "article { display: flex; }"
rule1.parentRule === rule0 // true
rule2.parentRule === rule1 // true(4)CSSRule.type
CSSRule.type属性返回一个整数值,表示当前规则的类型。
最常见的类型有以下几种。
- 1:普通样式规则(CSSStyleRule 实例)
- 3:
@import规则 - 4:
@media规则(CSSMediaRule 实例) - 5:
@font-face规则
CSSStyleRule 接口
如果一条 CSS 规则是普通的样式规则(不含特殊的 CSS 命令),那么除了 CSSRule 接口,它还部署了 CSSStyleRule 接口。
CSSStyleRule 接口有以下两个属性。
(1)CSSStyleRule.selectorText
CSSStyleRule.selectorText属性返回当前规则的选择器(可写)。
var stylesheet = document.styleSheets[0];
stylesheet.cssRules[0].selectorText // ".myClass"(2)CSSStyleRule.style
CSSStyleRule.style属性返回一个对象(CSSStyleDeclaration 实例),代表当前规则的样式声明,也就是选择器后面的大括号里面的部分。
// HTML 代码为
// <style id="myStyle">
// p { color: red; }
// </style>
var styleSheet = document.getElementById('myStyle').sheet;
styleSheet.cssRules[0].style instanceof CSSStyleDeclaration
// trueCSSStyleDeclaration 实例的cssText属性,可以返回所有样式声明,格式为字符串。
styleSheet.cssRules[0].style.cssText
// "color: red;"
styleSheet.cssRules[0].selectorText
// "p"CSSMediaRule 接口
如果一条 CSS 规则是@media代码块,那么它除了 CSSRule 接口,还部署了 CSSMediaRule 接口。
该接口主要提供media属性和conditionText属性。前者返回代表@media规则的一个对象(MediaList 实例),后者返回@media规则的生效条件。
window.matchMedia()
基本用法
window.matchMedia()方法用来将 CSS 的Media Query条件语句,转换成一个 MediaQueryList 实例。
var mdl = window.matchMedia('(min-width: 400px)');
mdl instanceof MediaQueryList // true上面代码中,变量mdl就是 mediaQueryList 的实例。
注意,如果参数不是有效的MediaQuery条件语句,window.matchMedia不会报错,依然返回一个 MediaQueryList 实例。
window.matchMedia('bad string') instanceof MediaQueryList // trueMediaQueryList 接口的实例属性
(1)MediaQueryList.media
MediaQueryList.media属性返回一个字符串,表示对应的 MediaQuery 条件语句。
var mql = window.matchMedia('(min-width: 400px)');
mql.media // "(min-width: 400px)"(2)MediaQueryList.matches
MediaQueryList.matches属性返回一个布尔值,表示当前页面是否符合指定的 MediaQuery 条件语句。
if (window.matchMedia('(min-width: 400px)').matches) {
/* 当前视口不小于 400 像素 */
} else {
/* 当前视口小于 400 像素 */
}下面的例子根据mediaQuery是否匹配当前环境,加载相应的 CSS 样式表。
var result = window.matchMedia("(max-width: 700px)");
if (result.matches){
var linkElm = document.createElement('link');
linkElm.setAttribute('rel', 'stylesheet');
linkElm.setAttribute('type', 'text/css');
linkElm.setAttribute('href', 'small.css');
document.head.appendChild(linkElm);
}(3)MediaQueryList.onchange
如果 MediaQuery 条件语句的适配环境发生变化,会触发change事件。MediaQueryList.onchange属性用来指定change事件的监听函数。
该函数的参数是change事件对象(MediaQueryListEvent 实例),该对象与 MediaQueryList 实例类似,也有media和matches属性。
var mql = window.matchMedia('(max-width: 600px)');
mql.onchange = function(e) {
if (e.matches) {
/* 视口不超过 600 像素 */
} else {
/* 视口超过 600 像素 */
}
}上面代码中,change事件发生后,存在两种可能。一种是显示宽度从600像素以上变为以下,另一种是从600像素以下变为以上,所以在监听函数内部要判断一下当前是哪一种情况。
MediaQueryList 接口的实例方法
MediaQueryList 实例有两个方法MediaQueryList.addListener()和MediaQueryList.removeListener(),用来为change事件添加或撤销监听函数。
var mql = window.matchMedia('(max-width: 600px)');
// 指定监听函数
mql.addListener(mqCallback);
// 撤销监听函数
mql.removeListener(mqCallback);
function mqCallback(e) {
if (e.matches) {
/* 视口不超过 600 像素 */
} else {
/* 视口超过 600 像素 */
}
}注意,MediaQueryList.removeListener()方法不能撤销MediaQueryList.onchange属性指定的监听函数。
Mutation Observer API
概述
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。
概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。
这样设计是为了应付 DOM 变动频繁的特点。举例来说,如果文档中连续插入1000个<p>元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;
而 Mutation Observer 完全不同,只在1000个段落都插入结束后才会触发,而且只触发一次。
Mutation Observer 有以下特点。
- 它等待所有脚本任务完成后,才会运行(即异步触发方式)。
- 它把 DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动。
- 它既可以观察 DOM 的所有类型变动,也可以指定只观察某一类变动。
构造函数
使用时,首先使用MutationObserver构造函数,新建一个观察器实例,同时指定这个实例的回调函数。
var observer = new MutationObserver(callback);上面代码中的回调函数,会在每次 DOM 变动后调用。该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例,下面是一个例子。
var observer = new MutationObserver(function (mutations, observer) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});实例方法
observe()
observe()方法用来启动监听,它接受两个参数。
- 第一个参数:所要观察的 DOM 节点
- 第二个参数:一个配置对象,指定所要观察的特定变动
var article = document.querySelector('article');
var options = {
'childList': true,
'attributes':true
} ;
observer.observe(article, options);上面代码中,observe()方法接受两个参数,第一个是所要观察的DOM元素是article,第二个是所要观察的变动类型(子节点变动和属性变动)。
观察器所能观察的 DOM 变动类型(即上面代码的options对象),有以下几种。
- childList:子节点的变动(指新增,删除或者更改)。
- attributes:属性的变动。
- characterData:节点内容或节点文本的变动。
想要观察哪一种变动类型,就在option对象中指定它的值为true。需要注意的是,至少必须同时指定这三种观察的一种,若均未指定将报错。
除了变动类型,options对象还可以设定以下属性:
subtree:布尔值,表示是否将该观察器应用于该节点的所有后代节点。attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。characterDataOldValue:布尔值,表示观察characterData变动时,是否需要记录变动前的值。attributeFilter:数组,表示需要观察的特定属性(比如['class','src'])。
// 开始监听文档根节点(即<html>标签)的变动
mutationObserver.observe(document.documentElement, {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
});对一个节点添加观察器,就像使用addEventListener()方法一样,多次添加同一个观察器是无效的,回调函数依然只会触发一次。如果指定不同的options对象,以后面添加的那个为准,类似覆盖。
下面的例子是观察新增的子节点。
var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++) {
insertedNodes.push(mutation.addedNodes[i]);
}
});
console.log(insertedNodes);
});
observer.observe(document, { childList: true, subtree: true });disconnect()
disconnect()方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。
observer.disconnect();takeRecords()
takeRecords()方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。
observer.takeRecords();下面是一个例子。
// 保存所有没有被观察器处理的变动
var changes = mutationObserver.takeRecords();
// 停止观察
mutationObserver.disconnect();对象
DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。
该实例包含了与变动相关的所有信息。Mutation Observer 处理的就是一个个MutationRecord实例所组成的数组。
MutationRecord对象包含了DOM的相关信息,有如下属性:
type:观察的变动类型(attributes、characterData或者childList)。target:发生变动的DOM节点。addedNodes:新增的DOM节点。removedNodes:删除的DOM节点。previousSibling:前一个同级节点,如果没有则返回null。nextSibling:下一个同级节点,如果没有则返回null。attributeName:发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。oldValue:变动前的值。这个属性只对attribute和characterData变动有效,如果发生childList变动,则返回null。
应用示例
子元素的变动
下面的例子说明如何读取变动记录。
var callback = function (records){
records.map(function(record){
console.log('Mutation type: ' + record.type);
console.log('Mutation target: ' + record.target);
});
};
var mo = new MutationObserver(callback);
var option = {
'childList': true,
'subtree': true
};
mo.observe(document.body, option);上面代码的观察器,观察<body>的所有下级节点(childList表示观察子节点,subtree表示观察后代节点)的变动。回调函数会在控制台显示所有变动的类型和目标节点。
属性的变动
下面的例子说明如何追踪属性的变动。
var callback = function (records) {
records.map(function (record) {
console.log('Previous attribute value: ' + record.oldValue);
});
};
var mo = new MutationObserver(callback);
var element = document.getElementById('#my_element');
var options = {
'attributes': true,
'attributeOldValue': true
}
mo.observe(element, options);上面代码先设定追踪属性变动('attributes': true),然后设定记录变动前的值。实际发生变动时,会将变动前的值显示在控制台。
取代 DOMContentLoaded 事件
网页加载的时候,DOM 节点的生成会产生变动记录,因此只要观察 DOM 的变动,就能在第一时间触发相关事件,也就没有必要使用DOMContentLoaded事件。
var observer = new MutationObserver(callback);
observer.observe(document.documentElement, {
childList: true,
subtree: true
});上面代码中,监听document.documentElement(即网页的<html>HTML 节点)的子节点的变动,subtree属性指定监听还包括后代节点。因此,任意一个网页元素一旦生成,就能立刻被监听到。
下面的代码,使用MutationObserver对象封装一个监听 DOM 生成的函数。
(function(win){
'use strict';
var listeners = [];
var doc = win.document;
var MutationObserver = win.MutationObserver || win.WebKitMutationObserver;
var observer;
function ready(selector, fn){
// 储存选择器和回调函数
listeners.push({
selector: selector,
fn: fn
});
if(!observer){
// 监听document变化
observer = new MutationObserver(check);
observer.observe(doc.documentElement, {
childList: true,
subtree: true
});
}
// 检查该节点是否已经在DOM中
check();
}
function check(){
// 检查是否匹配已储存的节点
for(var i = 0; i < listeners.length; i++){
var listener = listeners[i];
// 检查指定节点是否有匹配
var elements = doc.querySelectorAll(listener.selector);
for(var j = 0; j < elements.length; j++){
var element = elements[j];
// 确保回调函数只会对该元素调用一次
if(!element.ready){
element.ready = true;
// 对该节点调用回调函数
listener.fn.call(element, element);
}
}
}
}
// 对外暴露ready
win.ready = ready;
})(this);
// 使用方法
ready('.foo', function(element){
// ...
});网页元素接口
<a>元素接口
accessKey 属性
accessKey属性用来读写<a>元素的快捷键。
// HTML 代码如下
// <a id="test" href="http://example.com">test</a>
var a = document.getElementById('test');
a.accessKey = 'k';上面代码设置<a>元素的快捷键为k,以后只要按下这个快捷键,浏览器就会跳转到example.com。
注意,不同的浏览器在不同的操作系统下,唤起快捷键的功能键组合是不一样的。比如,Chrome 浏览器在 Linux 系统下,需要按下Alt + k,才会跳转到example.com。
download 属性
download属性表示当前链接不是用来浏览,而是用来下载的。它的值是一个字符串,表示用户下载得到的文件名。
// HTML 代码如下
// <a id="test" href="foo.jpg">下载</a>
var a = document.getElementById('test');
a.download = 'bar.jpg';上面代码中,<a>元素是一个图片链接,默认情况下,点击后图片会在当前窗口加载。设置了download属性以后,再点击这个链接,就会下载对话框,询问用户保存位置,而且下载的文件名为bar.jpg。
<img> 元素
浏览器提供一个原生构造函数Image,用于生成HTMLImageElement实例。
var img = new Image();
img instanceof Image // true
img instanceof HTMLImageElement // trueImage构造函数可以接受两个整数作为参数,分别表示<img>元素的宽度和高度。
// 语法
Image(width, height)
// 用法
var myImage = new Image(100, 200);<img>实例的src属性可以定义图像的网址。
var img = new Image();
img.src = 'picture.jpg';新生成的<img>实例并不属于文档的一部分。如果想让它显示在文档中,必须手动插入文档。
var img = new Image();
img.src = 'image1.png';
document.body.appendChild(img);属性
(1)HTMLImageElement.src
HTMLImageElement.src属性返回图像的完整网址。
(2)HTMLImageElement.currentSrc
HTMLImageElement.currentSrc属性返回当前正在展示的图像的网址。JavaScript 和 CSS 的 mediaQuery 都可能改变正在展示的图像。
<form> 元素
实例属性
elements:返回一个类似数组的对象,成员是属于该表单的所有控件元素。该属性只读。length:返回一个整数,表示属于该表单的控件数量。该属性只读。name:字符串,表示该表单的名称。method:字符串,表示提交给服务器时所使用的 HTTP 方法。target:字符串,表示表单提交后,服务器返回的数据的展示位置。action:字符串,表示表单提交数据的 URL。enctype(或encoding):字符串,表示表单提交数据的编码方法,可能的值有application/x-www-form-urlencoded、multipart/form-data和text/plain。acceptCharset:字符串,表示服务器所能接受的字符编码,多个编码格式之间使用逗号或空格分隔。autocomplete:字符串on或off,表示浏览器是否要对<input>控件提供自动补全。noValidate:布尔值,表示是否关闭表单的自动校验。
实例方法
submit():提交表单,但是不会触发submit事件和表单的自动校验。reset():重置表单控件的值为默认值。checkValidity():如果控件能够通过自动校验,返回true,否则返回false,同时触发invalid事件。
下面是一个创建表单并提交的例子。
var f = document.createElement('form');
document.body.appendChild(f);
f.action = '/cgi-bin/some.cgi';
f.method = 'POST';
f.submit();