文章目录
DOM操作
DOM(Document Object Modle,文档对象模型)是W3C定制的一套技术规范,用来描述js脚本如何与HTML或XML文档进行交互Web标准。DOM规定了一系列标准接口,允许开发人员通过标准方式访问文档结构、操作网页内容、控制样式和行为等。
【学习重点】
- 使用js操作节点。
- 使用js操作元素。
- 使用js操作文本和属性。
- 使用js操作文档和文档片段。
节点概述
在网页中所有的对象和内容都被称为节点,如文档、元素、文本、属性、注释等。节点(Node)是DOM最基本的单元,并派生出不同类型的节点,它们共同构成了文档的树形结构模型。
节点类型
根据DOM规范,整个文档是一个文档节点,每个标签是一个元素节点,元素包含的文本是文本节点,元素的属性是一个属性节点,注释属于注释节点,以此类推。
节点类型 | 说明 | 可包含的字节类型 |
---|---|---|
Document | 表示整个文档,DOM树的根节点 | Element、ProcessingInstruction、Comment、DocumentType |
DocumentFragment | 表示文档片段,轻量级的Document对象,仅包含部分文档 | ProcessingInstruction、Comment、Text、CDATASection、EntityReference |
DocumentType | 为文档定义实体提供接口 | None |
ProcessingInstruction | 表示处理指令 | None |
EntityReference | 表示实体引用元素 | ProcessingInstruction、Comment、Text、CDATASection、EntityReference |
Element | 表示元素 | Text、Comment、ProcessingInstruction、CDATASection、EntityReference |
Attr | 表示属性 | Text、EntityReference |
Text | 表示元素或属性中的文本 | None |
CDATASection | 表示文档中的CDATA区段,器包含的文本不会被解析器解析 | None |
Comment | 表示注释 | None |
Entity | 表示实体 | ProcessingInstruction、Comment、Text、CDATASection、EntityReference |
Notation | 表示在DTD中声明的符号 | None |
使用nodeType属性可以判断一个节点的类型。
节点类型 | nodeType返回值 |
---|---|
Element | 1 |
Attr | 2 |
Text | 3 |
CDATASection | 4 |
EntityReference | 5 |
Entity | 6 |
ProcessingInstruction | 7 |
Comment | 8 |
Document | 9 |
DocumentType | 10 |
DocumentFragment | 11 |
Notation | 12 |
- 【实例】下面实例演示如何借助节点的nodeType属性检查当前文档中包含元素的个数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
function count(n) {
var num = 0;
if (n.nodeType == 1) {
num++;
}
var son = n.childNodes;
for (var i = 0; i < son.length; i++) {
num += count(son[i]);
}
return num;
}
console.log("当前文档包含 " + count(document) + "个元素");
}
</script>
</head>
<body>
<h1>DOM</h1>
<p>DOM是<cite>Document Object Model</cite>首字母简写,中文翻译为<b>文档对象模型</b>,是<i>W3C</i>组织推荐的处理可扩展标识语言的标准编程接口</p>
<ul>
<li>D表示文档,HTML文档结构
</li>
<li>O表示对象,文档结构的js脚本化映射</li>
<li>M表示模型,脚本与结构交互的方法和行为</li>
</ul>
</body>
</html>
在上面的js脚本中定义了一个记数函数,然后通过递归调用的方式逐层检索document下做包含的全部节点,在计数函数中再通过node.nodeType == 1过滤掉非元素节点,进而统计文档中包含的全部元素。
节点名称和值
使用nodeName和nodeValue属性可以读取节点的名称和值。属性取值说明:
节点类型 | nodeName返回值 | nodeValue返回值 |
---|---|---|
Document | #document | null |
DocumentFragment | #document-fragment | null |
DocumentType | doctype名称 | null |
EntityReference | 实体引用名称 | null |
Element | 元素的名称 | null |
Attr | 属性的名称 | 属性的值 |
ProcessingInstruction | target | 节点的内容 |
Comment | #comment | 注释的文本 |
Text | #test | 节点的内容 |
CDATASection | #cdata-section | 节点的内容 |
Entity | 实体名称 | null |
Notation | 符号名称 | null |
- 【实例】不同类型的节点,nodeName和nodeValue属性取值不同。元素的nodeName属性返回值是标签名,而元素的nodeValue属性返回值为null。因此在读取属性值之前,应该先检测类型。
var node = document.getElementByTagName("body")[0];
if(node.nodeType==1) {
var value = node.nodeName;
}
console.log(value);
nodeName属性在处理标签时比较有用,而nodeValue属性在处理文本信息比较实用。
节点关系
DOM把文档视为一棵树型结构,也称为节点树。节点之间的关系包括:上下父子关系、相邻兄弟关系。简单描述如下:
- 在节点数中,最顶端节点为根节点。
- 除了根节点之外,每个节点都有一个父节点。
- 节点可以包含任何数量的子节点。
- 叶子是没有子节点的节点。
- 同级节点是拥有相同父节点的节点。
访问节点
DOM为Node类型定义如下属性,以便js访问节点。
- ownerDocument:返回当前节点的根元素(document对象)。
- parentNode:返回当前节点的父节点,所有的节点都仅有一个父节点。
- childNodes:返回当前节点的所有子节点的节点列表。
- firstChild:返回当前节点的第一个子节点。
- lastChild:返回当前节点的最后一个子节点。
- nextSibling:返回当前节点之后相邻的同级节点。
- previousSibling:返回当前节点之前相邻的同级节点。
- childNodes
childNodes返回所有子节点的列表,它是一个随时可变的类数组。文本节点和属性节点都不包含任何子节点,所以它们的childNodes属性返回值是一个空集合。可以使用haschildNodes()方法或者childNodes.length>0来判断一个节点是否包含子节点。
- parentNode
parentNode返回元素类型的父节点,因为只有元素才可能包含子节点。不过document节点没有父节点,document节点的parentNode属性将返回null。
- firstChild和lastChild
firstChild返回第一个子节点,lastChild返回最后一个子节点。文本节点和属性节点的firstChild和lastChild属性的返回值为null。
- 注意:firstChild等价于childNodes的第一个元素,lastChild属性值等于childNodes的最后一个元素。如果firstChild等于null,则说明当前节点为空节点。
- nextSibling和previousSibling
nextSibling返回下一个相邻节点,previousSibling返回上一个相邻点。如果没有同属性一个父节点的相邻节点,则返回null。
- ownerDocument
ownerDocument表示根节点。node.ownerDocument等价于document.documentElement。
操作节点
操作节点的基本方法:
方法 | 说明 |
---|---|
appendChild() | 向节点的子节点列表的结尾添加新的子节点 |
cloneNode() | 复制节点 |
hasChildNodes() | 判断当前节点是否拥有子节点 |
insetBefore() | 在指定的子节点前插入新的子节点 |
normalize() | 合并相邻的Text节点并删除 |
removeChild() | 删除(并返回)当前节点的指定子节点 |
replaceChild() | 用新节点替换一个子节点 |
- 提示:appendChild()、insertBefore()、removeChild()、replaceChild()四个方法用于对子节点进行操作。使用者四个方法之前,可以使用parentNode属性先获取父节点。另外,并不是所有类型的节点都有子节点,如果在不支持子节点,如果在不支持子节点的节点上调用了这些方法将会导致错误发生。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
var ul = document.getElementsByTagName("ul")[0];
ul.onclick = function() {
this.style.border = "solid blue 1px";
}
var ul1 = ul.cloneNode(true);
document.body.appendChild(ul1);
}
</script>
</head>
<body>
<h1>DOM</h1>
<p>DOM是<cite>Document Object Model</cite>首字母简写,中文翻译为<b>文档对象模型</b>,是<i>W3C</i>组织推荐的处理可扩展标识语言的标准变成接口</p>
<ul>
<li>D表示文档,HTML文档结构</li>
<li>O表示对象,文档结构为js脚本化映射</li>
<li>M表示模型,脚本与结构交互的方法和行为</li>
</ul>
</body>
</html>
文档节点
文档节点代表整个文档,使用document可以访问。它是文档内其他节点的访问入口,提供了操作其他节点的方法。主要特征值:nodeType等于9、nodeName等于“#document”、nodeValue等于null、parentNode等于null、ownerDocument等于null。
访问文档
在不同环境中,获取文档节点的方法不同。具体说法如下:
- 在文档内部节点,使用ownerDocument访问。
- 在脚本中,使用document访问。
- 在框架页,使用contentDocument访问。
- 在异步通信中,使用XMLHttpRequest对象的responseXML访问。
访问子节点
文档子节点包括以下类型:
- doctype文档类型,如
<!doctype html>
。 - html元素,如
<html>
。 - 处理指令,如
<?xml-stylesheet type="text/xsl" href="xsl.xsl"?>
。 - 注释,如
<!--注释-->
。
访问方法说明如下:
- 使用document.documentElement可以访问html元素。
- 使用document.doctype可以访问doctype。注意,部分浏览器不支持。
- 使用document.childNodes可以遍历子节点。
- 使用document.firstChild可以访问第一个子节点,一般为doctype。
- 使用docuemnt.lastChild可以访问最后一个子节点,如html元素或注释。
访问特殊元素
文档中存在很多特殊元素,使用下面的方法可以获取,若获取不到则返回null。
- 使用document.body可以访问body元素。
- 使用documetn.head可以访问head元素。
- 使用document.defaultView可以访问默认制图,即所属的窗口对象window。
- 使用document.scrollingElement可以访问文档内滚动的元素。
- 使用document.activeElement可以访问文档内获取焦点的元素。
- 使用document.fullscreenElement可以访问文档内正在全屏显示的元素。
访问元素集合
document包含一组集合对象,使用它们可以快速访问文档内元素,简单说明如下。
- document.anchors:返回设置name属性的
<a>
标签。 - document.links:返回所有设置了href属性的
<a>
标签。 - document.forms:返回所有form对象。
- document.images:返回所有image对象。
- document.applets:返回所有applet对象。
- document.enbeds:返回所有enbed对象。
- document.plugins:返回所有plugin对象。
- document.scripts:返回所有的script对象。
- document.styleSheets:返回所有样式表集合。
访问文档信息
document包含很多信息,简单说明如下:
- 静态信息:
- document.URL:返回当前文档的网址。
- document.domain:返回当前文档的域名,不包含协议和接口。
- document.location:访问location对象。
- docuemnt.lastModified:返回当前文档最后修改的时间。
- document.title:返回当前文档的标签。
- document.characterSet:返回当前文档的编码。
- document.referrer:返回当前文档的访问者在哪里。
- document.dir:返回文字方向。
- document.compatMode:返回浏览器处理文档的模式,值包括BackCompat(向后兼容模式)和CSS1Compat(严格模式)。
- 状态信息:
- document.hidden:表示当前页面是否可见。如果窗口最小化、切换页面,则document.hidden返回true。
- document.visibilitystate:返回文档的可见状态。取值包括visible(可见)、hidden(不可见)、prerender(正在渲染)、unloaded(已卸载)。
- document.readyState:返回当前文档的状态、取值包括loading(正在加载)、interactive(加载外部资源)、complete(加载完成)。
访问文档元素
docuement对象包含多个文档内元素的方法,简单说明如下:
- getElementById():返回指定id属性值的元素。注意,id值要区分大小写。,如果找到多个id相同的元素,则返回第一个元素;如果没有找到指定id值的元素,则返回null。
- getElementsByTagName():返回所有指定标签名的元素节点。
- getElementsByname():返回指定名称(name属性值)的元素节点。该方法多用于表单结构中,获取单选按钮组或复选框组。
提示:getElementByTagName()方法返回的是一个HTMLCollection对象,与nodeList对象类似,可以使用方括号语法或者item()方法访问HTMLCollection对象中的元素,并通过length属性取得这个对象中元素的数量。
元素节点
在客户端开发中,大部分操作都是针对元素节点的。主要特征值:nodeType等于1。nodeName等于标签名、nodeValue等于null。元素节点包含5个公共属性:id(标识符)、title(提示标签)、lang(语言编码)、dir(语言方向)、className(CSS类样式),这些属性可读可写。
访问元素
- getElementById()方法
使用getElementById()方法可以准确获取文档中指定元素。用法如下:
document.getElementById(ID);
参数ID表示文档中对应元素的id属性值。如果文档中不存在指定元素,则返回值为null。该方法只适用于document对象。
- 【实例1】在下面实例中,使用getElementById()方法获取
<div id="box">
对象,然后使用nodeName、nodeType、parentNode和childNodes属性查看该对象的节点类型、节点名称、父节点和第一个子节点的名称。
<div id="box">盒子</div>
<script>
var box = document.getElementById("box");
var info = "nodeName: " + box.nodeName;
info += "\rnodeType: " + box.nodeName;
info += '\rparentNode: ' + box.parentNode.nodeName;
info += "\rchildNodes: " + box.childNodes[0].nodeName;
console.log(info);
</script>
- getElementsByTagName()方法可以获取指定标签名称的所有元素。用法如下:
document.getElementsByTagName(tagName)
参数tagName表示指定标签名称的标签,该方法返回一个节点集合,使用length属性可以获取集合中包含元素的个数,利用下标可以访问其中某个元素对象。
- 【实例2】下面代码使用for循环获取每个p元素,并设置p元素的class属性为red。
var p = document.getElementsByTagName("p");
for (var i = 0; i < p.length; i++) {
p[i].setAttrbute("class","red");
}
创建元素
使用document对象的createElement()方法能够根据参数指定的标签名称创建一个新的元素,并返回新建元素的引用。用法如下:
var element = document.createElement("tagName");
其中,element表示新建元素的引用,createElement()是document对象的一个方法,该方法只有一个参数,用来执行创建元素的标签名称。
- 【实例1】下面代码在当前文档中创建了一个段落标记p,存储到变量p中。由于该变量表示一个元素节点,所以它的nodeType属性值等于1,而nodeName属性值等于p。
var p = document.createElement("p");
var info = "nodeName" + p.nodeName;
info += ",nodeType: " + p.nodeType;
console.log(info);
使用createElement()方法创建的新元素不会被自动添加到文档里。如果要把这个元素添加到文档里,还需要使用appendChild()、insertBefore或replaceChild()方法实现。
- 【实例2】下面代码演示如何把新建的p元素添加到body元素下。当元素被添加到文档树中就会立即显示出来。
var p = document.createElement("p");
document.body.appendChild(p);
复制节点
cloneNode()方法可以创建一个节点的副本。
插入节点
在文档中插入节点主要包括两种方法。
- appendChild()方法:
appendChild()方法可像当前节点的子节点列表的末尾添加新的子节点。用法如下:
appendChild(newchild)
参数newchild表示新添加的节点对象,并返回新增的节点。
- 【实例1】下面实例展示了如何把段落添加到文档中指定的div元素中,使它成为当前节点的最后一个子节点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
var p = document.createElement("p");
var txt = document.createTextNode("盒模型");
p.appendChild(txt);
document.getElementById("box").appendChild(p);
}
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
如果文档树中已经存在参数节点,则将从文档树中删除,然后重新插入新的位置。如果添加的节点是DocumentFragment节点,则不会直接插入,而是把它的子节点插入当前节点的结尾。
- 提示:将元素添加到文档树中,浏览器会立即呈现该元素。此后,对这个元素所做的任何修改都会实时反映在浏览器中。
- 【实例2】在下面实例中,新建两个盒子和一个按钮,使用CSS设计两个盒子显示为不同的效果;然后为按钮绑定事件处理程序,设计单击按钮时执行插入操作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<style>
#red {
border: solid red 20px;
}
#blue {
border: solid blue 10px;
}
</style>
<script>
window.onload = function() {
var ok = document.getElementById("ok");
ok.onclick = function() {
var red = document.getElementById("red");
var blue = document.getElementById("blue");
blue.appendChild(red);
}
}
</script>
</head>
<body>
<div id="red">
<h1>红盒子</h1>
</div>
<div id="blue">蓝盒子</div>
<button id="ok">移动</button>
</body>
</html>
上面代码使用appendChild()方法把红盒子移动到蓝盒子中间。在移动指定节点时,会同时移动指定节点包含的所有子节点。
- insertBefore()方法
使用insertBefore()方法可在已有的字节前插入一个新的子节点。
insertBefore(newchild, refchild);
其中参数newchild表示新插入的节点,refchild表示插入新节点的节点,用于指定插入节点的后面相邻位置。插入成功后,该方法将返回新插入的子节点。
- 提示:insertBefore()方法与appendChild()方法一样,可以把指定元素及其所包含的所有子节点都一起插入到指定位置中。同时会先删除移动的元素,再重新插入到新的位置。
删除节点
removeChild()方法可以从子节点列表中删除某个节点。
nodeObject.removeChild(node)
其中参数node为要删除节点。如果删除成功,则返回删除节点;如果失败,则返回null。
当使用removeChild()方法删除节点时,该节点所包含的所有子节点将同时删除。
- 【实例1】在下面的实例中单击按钮时将删除红盒子中的一级标题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<style>
#red {
border: solid red 20px;
}
#blue {
border: solid blue 10px;
}
</style>
<script>
window.onload = function() {
var ok = document.getElementById("ok");
ok.onclick = function() {
var red = document.getElementById("red");
var h1 = document.getElementsByTagName("h1")[0];
red.removeChild(h1);
}
}
</script>
</head>
<body>
<div id="red">
<h1>红盒子</h1>
</div>
<div id="blue">蓝盒子</div>
<button id="ok">移除</button>
</body>
</html>
替换节点
replaceChild()方法可以将某个子节点替换成另一个。
nodeObject.replaceChild(new_node, old_node)
其中参数new_node为指定新的节点,old_node为被替代的节点。如果替换成功,则返回被替换的节点;如果替换失败,则返回null。
- 【实例1】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<style>
#red {
border: solid red 20px;
}
#blue {
border: solid blue 10px;
}
</style>
<script>
window.onload = function() {
var ok = document.getElementById("ok");
ok.onclick = function() {
var red = document.getElementById("red");
var h1 = document.getElementsByTagName("h1")[0];
var h2 = document.createElement("h2");
red.replaceChild(h2, h1);
}
}
</script>
</head>
<body>
<div id="red">
<h1>红盒子</h1>
</div>
<div id="blue">蓝盒子</div>
<button id="ok">替换</button>
</body>
</html>
当替换之后,原来的一级标题已经不见了,说明替换节点的操作的不是替换元素的名称,而是替换其包含的所有子节点以及其包含的所有内容。
同样的道理,如果替换节点还包含子节点,则子节点将一同被插入到被替换的节点中。可以借助replaceChild()方法在文档中使用现有的节点替换另一个存在的节点。
文本节点
文本节点表示元素和属性的文本内容,包含纯文本内容、转义字符,但不包含HTML代码。文本节点不包含子节点。主要特征值:nodeType等于3、nodeName等于“#text”、nodeValue等于包含的文本。
创建文本节点
使用document对象的createTextNode()方法可以创建文本节点。
document.createTextNode(data)
参数data表示字符串。
- 【实例】下面实例创建一个新的div元素,并为他设置class值为red,添加到文档中。
var element = document.createElement("div");
element.className = "red";
document.body.appendChild(element);
注意:
由于DOM操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。为了避免这种情况的发生,一般会在父元素上调用normalize()方法,删除空文本节点,合并相邻文本节点。
访问文本节点
使用nodeValue或data属性可以访问文本节点包括的文本。使用length属性可以获取包含文本的长度,利用该属性可以遍历文本中每个字符。
- 【实例】
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
function text(e) {
var s = "";
var e = e.childNodes || e;
for (var i = 0; i < e.length; i++) {
s += e[i].nodeType != 1 ? e[i].nodeValue : text(e[i].childNodes);
}
return s
}
var div = document.getElementById("div1");
var s = text(div);
console.log(s); // div 元素
}
</script>
</head>
<body>
<div id="div1">
<span class="red">div</span> 元素
</div>
</body>
</html>
在上面函数中,通过递归函数索引指定元素的所有子节点,然后判断每个子节点的类型,如果不是元素,则读取该节点的值,否则继续递归遍历该元素包含的所有子节点。
读取HTML字符串
使用元素的innerHTML属性可以返回调用元素包含的所有子节点对应的HTML标记字符串。
插入HTML字符串
使用innerHTML属性可以根据传入的HTML字符串,创建新的DOM片段,然后这个DOM片段完全替代调用元素原有的所有子节点。设置innerHTML属性值之后,可以像访问文档中的其他节点一样访问新创建的节点。
- 注意:使用innerHTML属性也有一些限制。例如,在大多数浏览器中,通过innerHTML插入
<script>
标记后,并不会执行其中的脚本。
替换HTML字符串
outerHTML与innerHTML功能相同。
- 【实例】下面实例演示了outerHTML与innerHTML属性的不通效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
var ul = document.getElementsByTagName("ul")[0];
var lis = ul.getElementsByTagName("li");
lis[0].onclick = function() {
this.innerHTML = "<h2>我是一名初学者</h2>";
}
lis[1].onclick = function() {
this.outerHTML = "<h2>当然喜欢</h2>";
}
}
</script>
</head>
<body>
<h1>单击回答问题</h1>
<ul>
<li>你叫什么?</li>
<li>你喜欢JS么?</li>
</ul>
</body>
</html>
- 注意:在使用innerHTML、outerHTML时,应删除被替换元素的所有事件处理程序和js对象属性。
读写文本
innerText和outerText也是IE的私有属性,但是没有被HTML5纳入规范。
- innerText属性
innerText在指定元素中插入文本内容,如果文本中包含HTML字符串,将被编码显示。
- outerText属性
outerText与innerText功能类似,但是它能够覆盖原有的元素。
属性节点
属性节点的主要特征值:nodeType等于2、nodeName等于属性的名称、nodeValue等于属性的值、parentNode等于null,在HTML中不包含子节点。属性节点继承于Node类型,包括以下3个专用属性。
name:表示属性名称,等效于nodeName。
value:表示属性值,可读可写,等效于nodeValue。
specified:如果属性值在代码中设置的,则返回true;如果为默认值,则返回false。
创建属性节点
使用document对象的createAttribute()方法可以创建属性节点,具体用法如下:
document.createAttribute(name)
参数name表示新创建的属性的名称。
- 【实例1】下面实例创建一个属性节点,名称为align,值为center,然后为标签
<div id="box">
设置属性align,最后分别使用3种方法读取属性align的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
var element = document.getElementById("box");
var attr = document.createAttribute("align");
attr.value = "center";
element.setAttributeNode(attr);
console.log(element.attributes["align"].value); //center
console.log(element.getAttributeNode("align").value); //center
console.log(element.getAttribute("align")); //center
}
</script>
</head>
<body>
<div id="box">document.createAttribute(name)</div>
</body>
</html>
- 在传统DOM中,常用点语法通过元素直接访问HTML属性,如img.src、a.href等,这种方式虽然不标准,但是获得了所有浏览器的支持。
<img id="img1" src="">
<script>
var img = document.getElementByIn("img1");
img.setAttribute("src","http://www.w3.org/");
img.str = "http://www.w3.org/";
</script>
读取属性节点
使用元素的getAttribute()方法可以读取指定属性的值。用法如下:
getAttribute(name)
参数name表示属性名称。
- 注意:使用元素的attribute属性、getAttributeNode()方法可以返回对应属性节点。如上实例1。
- HTML DOM也支持使用点语法读取属性值,使用比较简便,也获得了所有浏览器的支持。
- 对于class属性,则必须使用className属性名,因为class是js语言的保留字;对于for属性,则必须使用htmlFor属性名,这与CSS脚本中float和text属性被改名为cssFloat和cssText是一个道理。
设置属性值
使用元素的setAttribute()方法可以设置元素的属性值。用法如下:
setAttribute(name, value);
参数name和value分别表示属性名称和属性值。属性名和属性值必须必须以字符串的形式进行传递。如果元素中存在指定的属性,它的值将被刷新;如果不存在,则setAttribute()方法将为元素创建该属性并赋值。
- 也可以使用快捷方式设置HTML DOM文档中元素的属性值。
<label id="label1">文本框:
<input type="text" name="textfield" id="textfield" />
</label>
<script>
var label = document.getElementByIn("label1");
label.className = "class1";
label.htmlFor = "textfield";
</script>
删除属性
使用元素的removeAttribute()方法可以删除指定的属性。
removeAttribute(name)
参数name表示元素的属性名。
使用类选择器
HTML5位document对象和HTML元素新增了getElementByClassName()方法,使用该方法可以选择指定类名的元素。getElementByClassName()方可以接受一个字符串参数,包括一个或多个类名。
- 【实例】下面实例使用document.getElementById(“box”)方法先获取
<div id="box">
,然后在它下面使用getElementByClassName(“blue red”)选择同时包含red和blue类的元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
var divs = document.getElementById("box").getElementsByClassName("blue red");
for (var i = 0; i < divs.length; i++) {
console.log(divs[i].innerHTML);
}
}
</script>
</head>
<body>
<div id="box">
<div class="blue red green">blue red green</div>
<div class="blue red black">blue red black</div>
</div>
</body>
</html>
- document对象上调用getElementByClassName()会返回类名匹配的所有元素,在元素上调用该方法就只会返回后代元素中匹配的元素。
自定义属性
HTML5允许用户为元素自定义属性,但要求添加data-前缀,目前是为元素提供与渲染无关的附加信息,或者提供语义信息。例如:
<div id="box" data-myid="12345" data-myname="zhangsan" data-mupass="zhang123">自定义数据属性</div>
添加自定义属性后,可以通过元素的dataset属性访问自定义属性。dataset属性的值是一个DOMStringMap实例,也就是一个名值对的映射。在这个映射中,每个data-name形式的属性都会有一个对应的属性,只不过属性名没有data-前缀。
var div = document.getElementById("box");
// 访问自定义属性值
var id = div.dataset.myid;
var name = div.dataset.myname;
var pass = div.dataset.mypass;
// 重置自定义属性值
div.dataset.myid = "54321";
div.dataset.myname = "lisi";
div.dataset.mypass = "lisi543";
// 检测自定义属性
if (div.dataset.myname) {
console.log(div.dataset.myname);
}
文档片段节点
DocumentFragment是一个虚拟的节点类型,仅存在于内存中,没有添加到文档数中,所以看不到渲染效果。使用文档片段你的好处,就是避免浏览器渲染和占用资源。当文档片段设计完善后,再使用js一次性添加到文档树中显示出来,这样可以提高效率。
主要特征值:nodeType值等于11、nodeName等于“#document-fragment”、nodeValue等于null、parentNode等于null。
创建文档片段的方法:
var fragment = document.createDocumentFragment();
使用appendChild()或insertBefore()方法可以把文档片段添加到文档树中。
每次使用js操作DOM都会改变页面呈现,并触发整个页面重新渲染(回流),从而消耗系统资源。为了解决这个问题,可以先创建一个文档片段,把所有新节点附加到文档片段上,最后再把文档片段一次性添加到文档中,减少页面重绘次数。
- 【实例】下面实例使用文档片段创建主流Web浏览器列表。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>test02</title>
<script>
window.onload = function() {
var element = document.getElementById("ul");
var fragment = document.createDocumentFragment();
var browers = ['Firefox', 'Chrome', 'Opera', 'Safari', 'Internet Explorer'];
browers.forEach(function(browser) {
var li = document.createElement("li");
li.textContent = browers;
fragment.appendChild(li);
});
element.appendChild(fragment);
}
</script>
</head>
<body>
<ul id="ul"></ul>
</body>
</html>
CSS选择器
- querySelector()
- querySelectorAll()
- 【实例1】新建网页文档,如下:
<div class="content">
<ul>
<li>首页</li>
<li class="red">财经</li>
<li class="blue">娱乐</li>
<li class="red">时尚</li>
<li class="blue">互联网</li>
</ul>
</div>
如果要获得第一个li元素,可以使用以下方法。
document.querySelector(".content ul li");
如果要获得宿友li元素,可以使用以下方法。
documet.querySelectorALl(".content ul li");
如果要获得所有的class为red的li元素,可以使用以下方法。
document.querySelectorAll("li.red");
- 提示:DOM API模块也包含getElementByClassName()方法,使用该方法可以获取指定类名的元素。
- 注意:getElementByClassName()方法只能够接受字符串,且为类名,而不需要加点号前缀,如果没有匹配到任何元素则返回空数组。
CSS选择器是一个便捷的确定元素的方法,这是因为大家对CSS已经很熟悉了。当需要联合查询时,使用querySelectorAll()更加便利。
- 【实例2】在文档中一些li元素的class名称是red,另一些是blue,可以用querySelectorAll()方法一次性获取这两类节点。
var lis = document.querySelectorAll("li.red, li.blue");
如果不使用querySelectorAll()方法,name要获取同样的列表,需要选择所有的li元素,然后通过迭代操作过滤出那些不需要的列表项目。
var result = [], lis1 = documentl.getElementByTagName('li'), classname = '';
for(var i = 0, len = lis1.length; i < len; i++){
classname = lis1[i].className;
if(classname === 'red' || classname === 'blue'){
result.push(list[i]);
}
}
比较上面两种方法,使用选择器querySelectorAll()方法比使用getElementByTagName()方法的性能要快得多。因此,如果浏览器支持document.querySelectorAll(),那么最好使用它。