DOM对象
DOM (document object model)文档对象模型
html css 组成了我们页面的内容,js是页面行为操作
DOM是打通js和html,css的一个工具,就是通过js来改变html和css
通过 JavaScript,您可以重构整个 HTML 文档。您可以添加、移除、改变或重排页面上的项目。
要改变页面的某个东西,JavaScript 就需要对 HTML 文档中所有元素进行访问的入口。这个入口,连同对 HTML 元素进行添加、移动、改变或移除的方法和属性,都是通过文档对象模型来获得的(DOM)。
在 1998 年,W3C 发布了第一级的 DOM 规范。这个规范允许访问和操作 HTML 页面中的每一个单独的元素。
所有的浏览器都执行了这个标准,因此,DOM 的兼容性问题也几乎难觅踪影了。
DOM 可被 JavaScript 用来读取、改变 HTML、XHTML 以及 XML 文档。
DOM节点
根据 DOM,HTML 文档中的每个成分都是一个节点。
DOM 是这样规定的:
整个文档是一个文档节点
每个 HTML 标签是一个元素节点
包含在 HTML 元素中的文本是文本节点
每一个 HTML 属性是一个属性节点
注释属于注释节点
所以一共四种节点。
通过 DOM,您可访问 HTML 文档中的每个节点。
查找并访问节点,你可通过若干种方法来查找您希望操作的元素:
通过使用 getElementById() 和 getElementsByTagName() 方法
通过使用一个元素节点的 parentNode、firstChild 以及 lastChild 属性
getElementById() 和 getElementsByTagName()
getElementById() 和 getElementsByTagName() 这两种方法,可查找整个 HTML 文档中的任何 HTML 元素。
这两种方法会忽略文档的结构。假如您希望查找文档中所有的 p 元素,getElementsByTagName() 会把它们全部找到,不管 p 元素处于文档中的哪个层次。同时,getElementById() 方法也会返回正确的元素,不论它被隐藏在文档结构中的什么位置。
这两种方法会像您提供任何你所需要的 HTML 元素,不论它们在文档中所处的位置!
getElementById() 可通过指定的 ID 来返回元素:
getElementById() 语法
document.getElementById(“ID”);
getElementsByTagName() 可被用于任何的 HTML 元素:
getElementsByTagName() 语法
document.getElementsByTagName(“标签名称”);
或者:document.getElementById(‘ID’).getElementsByTagName(“标签名称”);
节点列表(nodeList)
当我们使用节点列表时,通常要把此列表保存在一个变量中,就像这样:
var x=document.getElementsByTagName(“p”);
现在,变量 x 包含着页面中所有p元素的一个列表,并且我们可以通过它们的索引号来访问这些p元素,索引号从 0 开始。
getElementByClassName()
获取node节点下,所有符合条件的元素节点。
参数为:class
返回值: 返回所有符合条件的节点组成的一个数组
可以通过node.length 获取数组长
通过下标的方式获取某个节点 如 node[2]获取第三个节点
在ie浏览器中不支持用class获取,所以我们可以自己封装一个方法,达到兼容的效果
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
function elementByClassName(parent , classStr ) {
// 第一步找到parent下的所有元素节点,所以用通配符 '*'
var nodes = parent.getElementsByTagName("*");
var result = [];
alert(nodes.length)
for(var i = 0;i<nodes.length;i++){
if(nodes[i].className == classStr)
result.push(nodes[i]);
}
return result;
}
window.onload = function(){
var ul1 = document.getElementById("ul1")
var result = elementByClassName(ul1,"li1")
for(var i =0; i<result.length; i++)
console.log(result[i]);
}
</script>
</head>
<body>
<div>
<ul id="ul1">
<li class="li1">11111</li>
<li class="li1">22222</li>
<li class="li1">33333</li>
<li class="li1">44444</li>
<li class="li1">55555</li>
<li class="li1">66666</li>
</ul>
</div>
</body>
</html>
parentNode、firstChild以及lastChild
这三个属性 parentNode、firstChild 以及 lastChild 可遵循文档的结构,在文档中进行“短距离的旅行”。
请看下面这个 HTML 片段:
John | Doe | Alaska |
此外,tr 是每个 td元 素的父节点(parentNode)。
对 firstChild 最普遍的用法是访问某个元素的文本:
var x=[a paragraph];
var text=x.firstChild.nodeValue;
parentNode 属性常被用来改变文档的结构。假设您希望从文档中删除带有 id 为 “maindiv” 的节点:
var x=document.getElementById("maindiv");
x.parentNode.removeChild(x);
首先,您需要找到带有指定 id 的节点,然后移至其父节点并执行 removeChild() 方法。
根节点
有两种特殊的文档属性可用来访问根节点:
document.documentElement
document.body
第一个属性可返回存在于 XML 以及 HTML 文档中的文档根节点。
第二个属性是对 HTML 页面的特殊扩展,提供了对 标签的直接访问。
元素节点的属性:
- tagName:获取元素节点的标签名
- innerHTML:获取节点标签间的内容
- innerText:获取节点标签间的内容
- innerHTML设置或获取标签所包含的HTML+文本信息(从标签起始位置到终止位置全部内容,包括HTML标签,但不包括自身)
- innerText设置或获取标签所包含的文本信息(从标签起始位置到终止位置的内容,去除HTML标签,但不包括自身)
HTML属性:
id,title,style,className
访问这些属性: 通过 元素节点.属性名 或者 元素节点[属性名]
元素节点.style是一个style对象,所以要修改style中某个属性可以通过 元素节点.style.属性 来访问或修改
在style样式中,有一些样式是通过 — 链接的,这时候要把 — 去掉,然后将后续单词的首字母大写
如 TestDiv.style.backgroundColor 访问背景色
获取元素属性时遇到的浏览器兼容的问题:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div1{
width: 300px;
height: 300px;
background-color: red;
}
</style>
<script>
window.onload = function(){
var div1 = document.getElementById("div1");
/*
如果我们直接 div1.style.backgroundColor 是无法找到backgroundcolor的,这种操作只能获取行内定义的样式,不能获取到style标签内定义的
这时候可以通过 getComputedStyle(元素节点)[获取样式类型] 的方法获取当前有效样式
但是这个方法在ie浏览器中不支持,在ie浏览器中获取当前有效样式的方法是: 元素节点.currentStyle[获取样式类型];
*/
// alert(div1.style.backgroundColor); // 显示为空,因为找不到在外部style中定义的
// alert(getComputedStyle(div1).backgroundColor); //可以找到
// alert(div1.currentStyle); //ie中的方法
// 调用封装函数
alert(getStyle(div1,"backgroundColor"))
//这时候可以封装一个兼容的函数
function getStyle(elem,attr){
return elem.currentStyle ? elem.currentStyle[attr] : getComputedStyle(elem)[attr];
}
}
</script>
</head>
<body>
<div id="div1"> </div>
</body>
</html>
通过封装函数对几种获得节点的方法合成:
id -> document.getElementById(id)
tagName -> document.getElementsByTagName(TagName)
Name -> document.getElementsByName(Name)
className -> document.getElementsByClassName(ClassName)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
/*
封装一个函数,简化几个获取元素节点的方法
#id 通过id获取元素节点
.class 通过ClassName获取节点
tagName 通过tagName获取节点
name = xxx 通过name获取节点
*/
function $(vArg){
// 第一步: 对参数进行区分
switch(vArg[0]){
case "#":
return document.getElementById(vArg.substring[1]);
break;
case ".":
return elementByClassName(document,vArg.substring(1));
break;
default:
// 对参数前五个字符进行判断
var str = vArg.substring(0,5)
if(str == "name="){
return document.getElementsByName(vArg.substring(5));
}else{
return document.getElementsByTagName(vArg);
}
}
}
function elementByClassName(parent , classStr ) {
// 第一步找到parent下的所有元素节点,所以用通配符 '*'
var nodes = parent.getElementsByTagName("*");
var result = [];
alert(nodes.length)
for(var i = 0;i<nodes.length;i++){
if(nodes[i].className == classStr)
result.push(nodes[i]);
}
return result;
}
window.onload = function(){
var dddd = $("name=dddd")
alert(dddd)
var tag = $("div")
alert(tag)
}
</script>
</head>
<body>
<div name = "dddd"></div>
<div > </div>
</body>
</html>
getAttribute() 和 setAttribute() 方法方法
getAttribute(attributename) 方法通过名称获取属性的值。提示:如果你想返回属性请使用 getAttributeNode (attributename)方法。
elementNode.getAttribute(attributename)只有一个参数,就是想获取的属性值。
setAttribute(name,value)方法用于修改一个属性的值
elementNode.setAttribute(name,value):增加一个指定名称和值的新属性,或者把一个现有的属性设定为指定的值。name:要设置的属性名。value:要设置的属性值。
当然我们也可以直接通过 elementNode.元素属性名 的方法直接获取元素属性,但这种方式只能获取节点本来具有的属性,而getAttribute()可以获取自己定义的属性。而Attribute的家族还有setAttribute()和removeAttribute(),没错正如你想的英语单词的意思一样set (设置),remove(移除),这两个方法用来设置和移除节点原型中不存在的属性;
代码1:
<div id="case" create="hello"></div>
<div></div>
<script type="text/javascript">
var t = document.getElementById("case");
console.log(t.create); // 用直接获取的方法去获取自定义属性是无法获取的,所以是undefine
</script>
代码2:
<div id="case" create="hello"></div>
<div></div>
<script type="text/javascript">
var t = document.getElementById("case");
console.log(t.getAttribute("create")); //getAttribute可以获取自定义属性,所以是hello
</script>
childNodes 属性
获得 body 元素的子节点集合:document.body.childNodes;
childNodes 属性返回节点的子节点集合,以 NodeList 对象。可以使用 length 属性来确定子节点的数量,然后就能够遍历所有的子节点并提取您需要的信息。
childNodes 属性,标准的,它返回指定元素的子元素集合,包括HTML节点,所有属性,文本。可以通过nodeType来判断是哪种类型的节点,只有当nodeType==1时才是元素节点,2是属性节点,3是文本节点。
节点有三种非常有用的属性,nodeName,nodeValue,nodeType。
删除空白节点的代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var div1 = document.getElementById("div1");
// 这时候我们直接输出div1.childNodes.length,结果是5,因为回车,空格,换行,tab键 都属于一个节点
console.log(div1.childNodes.length)
// 这时候我们想办法去除掉空白节点。所以我们必须识别出空白节点
var result = removeSpaceNode(div1.childNodes);
console.log(result.length)
for(var i=0; i< result.length; i++)
console.log(result[i]);
// 或者使用这个函数,直接在原来的节点基础上删除
function removeSpaceNode2( parent ){
var nodes = parent.childNodes;
// 在删除的时候,必须要倒删,
for(var i=nodes.length-1; i>=0; i--){
if(nodes[i].nodeType == 3 && /^\s+$/.test(nodes[i].nodeValue)){
parent.removeChild(nodes[i]);
}
}
}
// /^\s+$/.test(); 可以使用这个正则表达式来判断是否是空白节点
// 创建一个函数用来删除空白节点
function removeSpaceNode( nodes ){
var result = []; // 用于存放不是空白节点的节点
for(var i=0; i<nodes.length; i++){
// 判断一下是不是空白节点
if(nodes[i].nodeType == 3 && /^\s+$/.test(nodes[i].nodeValue)){
continue; // 空白节点什么都不做
}else{
result.push(nodes[i]);
}
}
return result;
}
}
</script>
</head>
<body>
<div id="div1">
<em>斜体</em>
文本内容
<strong>粗体</strong>
</div>
</body>
</html>
访问节点
通过节点之间的树形关系,可以定位文档中的每个节点。DOM为Node类型定义如下属性,以方便JavaScript对文档树中每个节点进行遍历。
- ownerDocument:返回当前节点的根元素(document对象)
- parentNode:返回当前节点的父节点。所有的节点都仅有一个父节点
- childNodes:返回当前节点的所有子节点的节点列表
- firstChild:返回当前节点的首个子节点
- lastChild:返回当前系欸但的最后一个子节点
- nextSibling:返回当前节点之后相邻的同级节点
- previousSibling:返回当前节点之前相邻的同级节点
write() 方法
write() 方法可向文档写入 HTML 表达式或 JavaScript 代码。可列出多个参数(exp1,exp2,exp3,…) ,它们将按顺序被追加到文档中。
语法:document.write(exp1,exp2,exp3,…)
一些说明:说明虽然根据 DOM 标准,该方法只接受单个字符串作为参数。不过根据经验,write() 可接受任何多个参数。还有我们通常按照两种的方式使用 write() 方法:一是在使用该方在文档中输出 HTML,另一种是在调用该方法的的窗口之外的窗口、框架中产生新文档。在第二种情况中,请务必使用 close() 方法来关闭文档。
【注】:在添加内容时,会将原有的页面上的内容覆盖掉
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#div1{
width: 300px;
height: 300px;
background-color: red;
}
</style>
<script>
window.onload = function(){
var btn = document.getElementById("btn");
btn.onclick = function(){
document.write("<h1>我是标题内容</h1>")
}
}
</script>
</head>
<body>
<div id="div1"></div>
<button id="btn"> 按钮 </button>
</body>
</html>
创建节点
createElement()和createTextNode()
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
<script>
/*
createElement()
[格式] document.creatElement(标签名);
createTextNode(文本内容),创建一个文本节点
注意创建完标签,使用appendChild把标签插入到相对应的地方
*/
window.onload = function(){
var btn = document.getElementById("btn");
var div = document.getElementById("div1");
btn.onclick = function(){
// 创建一个span标签
var node = document.createElement("span");
// 给span标签赋值
node.innerText = "这是新建的span标签"
// 把新创建的标签插入到相对应的节点中
div.appendChild(node)
// 当然上面三个步骤太麻烦,我们可以直接封装一个函数来实现创建带文本的节点
var newnode = createElementWidthTxt("p","我是用封装函数新创建的p")
div.appendChild(newnode);
}
}
function createElementWidthTxt( tagName, txt){
var node = document.createElement(tagName);
var nodeTxt = document.createTextNode(txt);
node.appendChild(nodeTxt);
return node;
}
</script>
</head>
<body>
<div id="div1">
</div>
<button id="btn"> 按钮 </button>
</body>
</html>
插入节点
insertBefore() 方法在您指定的已有子节点之前插入新的子节点。
提示:如果您希望创建包含文本的新列表项,请记得创建文本节点形式的文本,以便追加到 LI 元素中,然后向列表插入这个 LI。
您也可以使用 insertBefore 方法插入/移动已有元素。
参数:
newnode Node对象。必需。需要插入的节点对象。
existingnode Node object 可选。在其之前插入新节点的子节点。如果未规定,则 insertBefore 方法会在结尾插入 newnode。
但是js没有提供insertAfter方法,所以我们要自己封装一个
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
window.onload = function(){
var node = document.createElement("strong");
var oldSpan = document.getElementById("oldSpan");
node.innerHTML = "我是新创建的节点";
insertAfter(node,oldSpan);
}
// 封装一个函数,用于在某个节点之后插入
function insertAfter(newNode , oldNode){
// 先判断oldNode是否是最后一个节点,如果是最后一个节点我们直接在最后插入,如果不是最后一个节点我们就要先找到这个oldNode的后一个,在这个后一个节点前插入
var parent = oldNode.parentNode; // 找到父节点
if( oldNode == parent.lastNode ){ // 如果是最后一个节点,直接插入最后就行
parent.appenchild(newNode);
}else{
parent.insertBefore(newNode , oldNode.nextSibling); // 不是最后一个节点,就在oldNode的后一个节点前插入
}
}
</script>
</head>
<body>
<div id="div1">
<p>p</p>
<span id="oldSpan">span</span>
<em>em</em>
</div>
</body>
</html>
replacechild() 和cloneNode()和removechild()方法
将某个子节点替换为另一个:document.getElementById(“myList”).replaceChild(newnode,oldnode);
replaceChild() 方法可将某个子节点替换为另一个。新节点可以是文本中已存在的,或者是你新创建的
cloneNode() 方法可创建指定的节点的精确拷贝。cloneNode() 方法 拷贝所有属性和值。该方法将复制并返回调用它的节点的副本。如果传递给它的参数是 true,它还将递归复制当前节点的所有子孙节点。否则,它只复制当前节点。
removechild()从子节点列表中删除某个节点;removeChild() 方法可从子节点列表中删除某个节点。如删除成功,此方法可返回被删除的节点,如失败,则返回 NULL。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
/*
replaceChild() 节点替换
cloneNode() 克隆节点
removeChild() 删除节点
*/
window.onload = function(){
var div = document.getElementById("div1");
var node = document.createElement("strong");
var pNode = document.getElementById("p1");
div.parentNode.replaceChild(node,div); // 先找到div的父节点,然后利用父节点调用替换节点还书
var cloneNewNode = div.cloneNode(); // 先复制一个节点,然后放入
node.parentNode.appendChild(cloneNewNode);
pNode.parentNode.removeChild(pNode) // 先找到被删除节点的父节点,然后利用该父节点删除这个节点
}
</script>
</head>
<body>
<span> span </span>
<div id="div1"></div>
<p id="p1">p</p>
</body>
</html>