DOM:文档对象模型
作用: 使javascript有能力操作HTML文档(获取HTML标记元素,添加HTML标记元素,删除HTML标记元素等)
属性:内置属性和非内置属性(自定义属性)
DOM的分类:
核心 DOM
提供了操作HTML元素的属性和方法
遍历DOM树、添加新节点、删除节点、修改节点
HTML DOM
提供了查找改变HTML元素的属性和方法
以一种简便的方法访问DOM树
CSS DOM
提供了操作CSS的属性和方法
事件 DOM
事件对象模型,eg:onclick
DOM树:
节点关系:
根节点:一个HTML文档只有一个根,它就是HTML节点。
子节点:某一个节点的下级节点。
父节点:某一个节点的上级节点。
兄弟节点:两个子节点同属于一个父节点。
节点的分类:
【属性节点(attribute)】,指定是HTML标签的属性
【文本节点(text)】,指定是HTML标签的内容
【空白节点】,在主流浏览器中标签和标签之间的换行会理解为一个空白节点,在IE浏览器中不会
下面来详细的讲解:
一、DOM选择器
getElementById(id)
描 述:获取网页指定id名字的元素,返回一个对象
语 法:var obj = document.getElementById("id名称")
参 数:id名称(注:需要加引号)
返回值:对象,对象的属性就是HTML标签的属性
getElementsByTagName()
功 能:获取网站指定标签名称的元素
语 法:var obj = document.getElementsByTagName("标签名称")
参 数:标签名称(注:需要加引号)
返回值:返回一个集合(数组),集合中每个元素都是一个单独标签对象
getElementsByName()
功 能:通过标签的name值获取元素
语 法:var obj = document.getElementsByName() ("标签name名称")
参 数:标签的name名称(注:需要加引号)
返回值:返回值是数组,通常用来获取有name的input的值
getElementsByClassName()
功 能:通过class名获取元素
语 法:var obj = document.getElementsByClassName() ("标签的class属性名称")
参 数:标签的class属性名称(注:需要加引号)
返回值:返回值是数组
ES5选择器:(可以直接填写,eg:标签名,类名,id名称)
document.querySelector(); //返回匹配到的第一个元素
document.querySelectorAll(); //返回一个数组,哪怕只有一个元素
注:
1.不是所有标签都有name值
2.在低版本的浏览器中,getElementsByName和getElementsByClassName有兼容性
//body
<div id="a" class="ab">aa ab</div>
<div class="ab">abab</div>
<span>span1span</span>
<span>span2span</span>
<input type="button" value="button" name="btn" >
//js
var aObj = document.getElementById("a")
console.log(aObj); //<div id="a" class="ab">aa ab</div>
var spanObj = document.getElementsByTagName("span");
//console.log(spanObj);
console.log(spanObj[0]);
var btnObj = document.getElementsByName("btn");
//console.log(btnObj);
console.log(btnObj[0]);
var abObj = document.getElementsByClassName("ab");
//console.log(abObj);
console.log(abObj[1]);
var Obj1 = document.querySelector("#a");
var Obj2 = document.querySelector(".ab");
var Obj3 = document.querySelector("span");
console.log(Obj1);
console.log(Obj2);
console.log(Obj3);
var Objo1 = document.querySelectorAll("span");
var Objo2 = document.querySelectorAll(".ab");
// console.log(Objo1);
console.log(Objo1[1]);
// console.log(Objo2);
console.log(Objo2[0]);
二、DOM属性
1.内置属性
内置属性可以直接通过点"."进行操作
tagName //返回值是当前元素的标签名
innerHTML/innerText //返回值是当前元素的内容
id //返回值是当前元素的ID
title //获取title的标签值,这个title是从document中获取的
className //返回值是当前元素的class
href //返回值是当前的href的值
以上这些属性既可以获取,也可以设置
2.非内置属性(自定义属性)
非内置属性需要通过一些节点的方法进行操作,注意:节点的方法,前缀一定是节点
getAttribute(name) //获取指定对象的属性名的属性值
console.log(obox.getAttribute("num"))
setAttribute(name,value) //设置/修改 元素的属性,低版本的IE不兼容;接收两个参数,属性名和属性值
obox.setAttribute("num","110")
removeAttribute(name) //删除 元素的属性,低版本的IE不兼容
obox.removeAttribute("num")
//body
<input type="text" name="ipt" value="10">
<span num="10" id="sp">222</span>
//js
var ipt = document.getElementsByName("ipt")[0];
var sp = document.getElementById("sp");
//获取属性值
console.log(sp.getAttribute("num"));
//修改属性值
sp.setAttribute("num",110);
console.log(sp);
ipt.setAttribute("value",20);
console.log(ipt);
//删除元素属性
sp.removeAttribute("num")
console.log(sp)
三、节点
根据DOM规定,HTML文档中的每个成分都是一个节点。
DOM是这样规定的:
整个文档是一个 文档节点
每个HTML标签是一个 元素节点
包含在HTML元素中的文本是 文本节点
每一个HTML属性是一个 属性节点
注释属于 注释节点
相当于HTML文档中的所有内容都是节点,元素是节点的别称,节点包含元素,当然节点还有好多细化的种类
节点 | 节点类型(nodeType) | 节点名字(nodeName) | 节点值(nodeValue) |
---|---|---|---|
元素节点 | 1 | 标签名 | null |
文本节点 | 3 | #text | 文本 |
注释节点 | 8 | #comment | 注释的文字 |
文档节点 | 9 | #document | null |
属性节点 | 2 | 属性名 | 属性值 |
//body
<ul class="a" id="b" zidingyi="c">
文本
<li>1</li>
<li>2</li>
<!-- 注释 -->
<li>3</li>
</ul>
//js
var ulObj = document.getElementsByTagName("ul")[0];
console.log(ulObj);
var child = ulObj.childNodes;
console.log(child); //9个节点 [text, li, text, li, text, comment, text, li, text]
console.log(ulObj.children); //[li, li, li]
//节点类型--》节点名字--》节点值
// nodeType只能获取不能设置
// nodeName只能获取不能设置
// nodeValue 能获取能设置
console.log(typeof child[0]); //object
console.log(child[0].nodeType); //3,表示文本
console.log(child[0].nodeName); // #text
console.log(child[0].nodeValue); // 文本
console.log(typeof child[1]); //object
console.log(child[1].nodeType); //1,表示元素
console.log(child[1].nodeName); // LI
console.log(child[1].nodeValue); // null
console.log(typeof child[5]); //object
console.log(child[5].nodeType); //8,表示注释
console.log(child[5].nodeName); // #comment
console.log(child[5].nodeValue); // 注释
//返回元素的根节点
var liObj = document.getElementsByTagName("li")[0];
console.log(liObj.ownerDocument); //#document
console.log(ulObj.ownerDocument); //#document
console.log(liObj.ownerDocument.nodeType); //9,表示文档
console.log(liObj.ownerDocument.nodeName); // #document
console.log(liObj.ownerDocument.nodeValue); // null
//节点属性
var oAttr = ulObj.attributes;
console.log(oAttr); //{0: class, 1: id, 2: zidingyi, class: class, id: id, zidingyi: zidingyi, length: 3}
console.log(oAttr[0]); //class="a"
console.log(oAttr[0].nodeName); //class
console.log(oAttr[0].nodeValue); //a
console.log(oAttr[0].nodeType); //2
console.log(oAttr[1]); //id="b"
console.log(oAttr[1].nodeName); //id
console.log(oAttr[1].nodeValue); //b
console.log(oAttr[1].nodeType); //2
console.log(oAttr[2]); //zidingyi="c"
console.log(oAttr[2].nodeName); //zidingyi
console.log(oAttr[2].nodeValue); //c
console.log(oAttr[2].nodeType); //2
获取DOM节点:
对象.parentNode //获得父元素节点
对象.children //获得子元素节点的集合,不包含空白节点
//但IE7包含首个注释节点(前面没有元素节点),IE8包含所有注释节点
对象.childNodes //获取当前元素节点的所有子节点的集合,包括空白节点
//IE7/8不包含空文本节点,但IE7包含首个注释节点(前面没有元素节点),IE8包含所有注释节点
对象.ownerDocument //获取该节点的文档根节点,相当与 document
对象.firstChild //获得第一个子节点。(包含空白,IE7/8非空白节点,可能是注释节点)
对象.firstElementChild //获得第一个非空白的子节点。(IE7/8不支持)
对象.lastChild //获得最后一个子节点(IE7最后一个元素节点,IE8最后一个非空白节点,可能是注释节点)
对象.lastElementChild //获得最后一个非空白的子节点。(IE7/8不支持)
对象.nextSibling //获得下一个兄弟节点。(包含空白节点和注释,IE7/8包括注释节点,不包括空白节点)
对象.nextElementSibling //获得下个兄弟节点。(IE7/8不支持)
对象.previousSibling //获得上一个兄弟节点。(包含空白节点和注释。IE7/8包括注释节点,不包括空白节点)
对象.previousElementSibling //获得上一个兄弟节点。(IE7/8不支持)
nodeName:返回节点名字
nodeValue:返回节点值 (针对文本节点)
如何获取属性节点:
对象.attributes //获得所有属性节点,返回一个数组
//body
<ul>
<li>one</li>
<li>two</li>
<li>123</li>
<li>three</li>
</ul>
<input type="text" id="ipt" value="10">
//js
//document 表示文档本身
console.log(document); //#document
var first = document.firstChild;
console.log(first);
var last = document.lastChild;
console.log(last);
//获取body节点
var bodyObj = last.lastChild;
console.log(bodyObj); //<body>...</body>
//获取ul节点
var ulObj = bodyObj.firstChild;
console.log(ulObj); //#text,会获取空白节点
var ulObj1 = bodyObj.firstElementChild;
console.log(ulObj1); //<ul>...</ul>
//获取ul节点下的第一个li
var liObj = ulObj1.firstElementChild;
console.log(liObj); //<li>one</li>
//获取ul节点下的第二个li
var liObj2 = liObj.nextElementSibling;
console.log(liObj2); //<li>two</li>
//获取ul节点下的第三个li
var liObj3 = liObj.nextElementSibling.nextElementSibling;
console.log(liObj3); //<li>123</li>
// 或者
var liObj3_1 = ulObj1.lastElementChild.previousElementSibling;
console.log(liObj3_1); //<li>123</li>
//获取ul节点下的最后一个li
var liObj4 = ulObj1.lastElementChild;
console.log(liObj4); //<li>three</li>
//获取节点名称
var nameObj = document.body.nodeName;
console.log(nameObj); //BODY
var nameObj1 = ulObj1.nodeName;
console.log(nameObj1); //UL
//获取文本节点
var textObj = liObj.firstChild;
console.log(textObj); //"one"
//获取节点值
var liValue = textObj.nodeValue;
console.log(liValue); //one
//获取父节点
var fuObj = liObj.parentNode;
console.log(fuObj); //<ul>...</ul>
//获取子节点
var ziObj = ulObj1.children;
console.log(ziObj); //不包含空白节点,[li,li,li,li]
var ziObj1 = ulObj1.childNodes;
console.log(ziObj1); //包含空白节点,[text, li, text, li, text, li, text, li, text]
//获取文档根节点,相当一document
var root = liObj.ownerDocument;
console.log(root); //#document
var root1 = ulObj1.ownerDocument;
console.log(root1); //#documnet
//获取属性节点
var ulAtr = document.getElementById("ipt");
var atr = ulAtr.attributes;
console.log(atr)
四、DOM的增 / 删 / 改 / 查
节点创建
元素节点:document.createElement(tag标签名称);
文本节点:document.createTextNode(文本内容);
属性设置:node.setAttribute(名称,值);
节点追加(插入节点)
父节点.appendChild(子节点); // 向父节点添加最后一个子节点
父节点.insertBefore(newnode,oldnode); // 将newnode放到oldnode的前边
节点删除
父节点.removeChild(子节点); //删除父节点下的某个子节点
元素.remove(); //直接删除当前元素
节点查询:选择器
增 / 删 / 改 / 查:
//body
<span>span-span</span>
<ul id="list">
<li>link1</li>
<li>link2</li>
<li>link3</li>
</ul>
//js
var spanObj = document.getElementsByTagName("span")[0];
var list = document.getElementById("list");
//增
var crtDiv = document.createElement("div");
var divText = document.createTextNode("div-div");
var crtLi = document.createElement("li");
var liText = document.createTextNode("link4");
var crtbfLI = document.createElement("p");
var libfText = document.createTextNode("p标签");
//将文本放到div中,并将div作为父元素的最后一个子节点(默认)
crtDiv.appendChild(divText);
document.body.appendChild(crtDiv);
console.log(document.body.lastElementChild) //见图1
//将文本放在li中,并作为ul的最后一个子元素
crtLi.appendChild(liText);
list.appendChild(crtLi);
//为link4增加一个className
crtLi.className = "li4";
console.log(document.body.firstElementChild.nextElementSibling); //见图2
//将p标签插入到ul前
crtbfLI.appendChild(libfText);
document.body.insertBefore(crtbfLI,list);
console.log(document.body); //见图3
//删
//删除div标签
document.body.removeChild(crtDiv);
console.log(document.body); //见图4
//删除ul标签
list.remove();
console.log(document.body) //见图5
//改
spanObj.innerHTML = "修改后的span标签";
console.log(spanObj); //<span>修改后的span标签</span>
//或者
spanObj.outerHTML = "<span>" + spanObj.innerHTML + "</span>"
//查
console.log(document.body.firstElementChild); //<span>修改后的span标签</span>
补充:
- css DOM:
- color:red;
- obj.style.color = ‘red’;
- obj.style.background = ‘red url()’
- obj.style.fontSize = ;
- obj.style.width = “400px”;
- color:red;
上面虽然可以解决部分问题,但是对应非行内样式来说,会出现一些小问题,如下:
//style
.test{height:200px;}
//body
<div style="width:200px" class="test" id="id">非行内样式的获取</div>
//js
var obj = document.getElementById("id");
console.log(obj.style.height); //显示为空
console.log(getComputedStyle(obj).height); //200px,用于非ie浏览器
// console.log(obj.currentStyle["height"]); //用于ie浏览器
因此我们可以封装一个函数来兼容它:
//获取非行内样式(兼容问题)
function getStyle(obj,attr){ //获取非行间样式,obj是对象,attr是值
if(obj.currentStyle){ //针对ie获取非行间样式
return obj.currentStyle[attr];
}else{
//false表示不是获取obj的伪类,true表示获取obj的伪类
return getComputedStyle(obj,false)[attr]; //针对非ie
};
};
五、浏览器尺寸
Method | 描述 |
---|---|
offsetParent | 获取元素的最近的具有定位属性(absolute或者relative)的父级元素。如果都没有则返回body |
offsetLeft | 表示元素的左外边框至父级元素(offsetParent)的左内边框之间的像素距离 |
offsetTop | 表示元素的上外边框至父级元素(offsetParent)的上内边框之间的像素距离 |
scrollLeft / scrollTop | 滚动条最顶端和窗口中可见内容的最顶端之间的距离 |
clientWidth / clientHeight | 元素视窗宽度/高度 |
offsetWidth / offsetHeight | 元素实际宽度/高度 |
clientWidth = width+左右padding
clientHeight = height + 上下padding
offsetWidth / offsetHeight:元素实际宽度/高度
offsetWidth = width + 左右padding + 左右boder
offsetHeiht = height + 上下padding + 上下boder
offsetLeft = margin + position
scrollHeight = height + padding + scroll
// 浏览器尺寸
//style
*{margin:0;}
#box{width: 500px;height: 500px;border:2px solid #00f;position: relative;left: 100px;top: 200px;padding:10px 5px;}
#box1{width: 100px;height: 100px;border: 2px solid #000;position:absolute;left: 150px;top:250px;}
//body
<div id="box">
<div id="box1"></div>
</div>
//js
var boxObj = document.querySelector("#box");
var box1Obj = document.querySelector("#box1");
//获取最近的具有定位属性的父级元素,若都没有则返回body
console.log(boxObj.offsetParent);
console.log(box1Obj.offsetParent);
//元素左外边框至父级元素左内边框的距离
console.log(boxObj.offsetLeft); //100
console.log(box1Obj.offsetLeft); //150
//元素上外边框至父级元素上内边框的距离
console.log(boxObj.offsetTop); //200
console.log(box1Obj.offsetTop); //250
box1Obj.style.top = "100px";
console.log(box1Obj.offsetTop); //100
//元素视窗宽度/高度
console.log(boxObj.clientWidth); //510
console.log(boxObj.clientHeight); //520
console.log(box1Obj.clientWidth); //100
console.log(box1Obj.clientHeight); //100
//元素实际宽度/高度
console.log(boxObj.offsetWidth); //514
console.log(boxObj.offsetHeight); //524
console.log(box1Obj.offsetWidth); //104
console.log(box1Obj.offsetHeight); //104
scrollLeft / scrollTop | 滚动条最顶端和窗口中可见内容的最顶端之间的距离
//body
<div id="out" style="height: 200px;width: 200px;border: 5px solid #000;padding: 50px;overflow: auto;">
<div id="inn" style="height: 400px;width:400px;border: 5px solid blue;">111</div>
</div>
//js
var out = document.querySelector("#out");
out.scrollLeft = 100;
out.scrollTop = 100;
console.log(out.scrollTop); //100
console.log(out.scrollLeft); //100
console.log(out.scrollHeight); //510
console.log(out.scrollWidth); //460
六、案例
1.模拟tab切换页面
//css
*{margin: 0;padding: 0;list-style: none;}
.count{width: 600px;height: 400px;margin:50px auto;border: solid 1px black;}
.count ul{height: 72px;}
.count ul li{width: 199px;height:72px;font: 24px/3 "";float: left;text-align: center;border-bottom: solid 1px black;border-right: solid 1px black;}
.msg div{height: 328px;color: #fff;font:40px/300px "微软雅黑";display: none;text-align: center;}
.msg div:nth-child(1){background: green;}
.msg div:nth-child(2){background: red;}
.msg div:nth-child(3){background: blue;}
.count li.active{background: #ccc;}
.count div.active{display: block;}
//body
<div class="count">
<ul>
<li class="active">资源1</li>
<li>资源2</li>
<li>资源3</li>
</ul>
<div class="msg">
<div class="active">msg1</div>
<div>msg2</div>
<div>msg3</div>
</div>
</div>
//js
var ali = document.querySelector("ul").children;
var adiv = document.querySelector(".msg").children;
//遍历li
for(var i = 0;i<ali.length;i++){
ali[i].index = i;
ali[i].onclick = function(){
//遍历div
for(var j = 0;j<adiv.length;j++){
ali[j].className = "";
adiv[j].className = "";
}
//点中的li的className设为active
this.className = "active";
//点中的li对应的div的className设为active
adiv[this.index].className = "active"
}
}