PS(图中出现珠峰为某教育机构,并非打广告,因本人较懒,课件没有修改)
DOM: Document Object Model(文档对象模型)
DOM树:
回流和重绘
重绘(repaint):
当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要 UI 层面的重新像素绘制,因此损耗较少。
常见的重绘操作有:
- 改变元素颜色
- 改变元素背景色
- more ……
回流(reflow):
又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。
常见的回流操作有:
- 页面初次渲染
- 浏览器窗口大小改变
- 元素尺寸/位置/内容发生改变
- 元素字体大小变化
- 添加或者删除可见的 DOM 元素
- ……
重点:回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。
DOM 操作
1、获取元素
1.1 根据id名获取
document.getElementById(idName)
1.2 根据标签名获取
document.getElementsByTagName(tagName) // 返回一个集合 (类数组对象) 从整个文档获取
element.getElementsByTagName(tagName) // 从element的后代元素中获取
1.3 根据类名获取(不兼容ie6~8)
document.getElementsByClassName(className) // 返回一个集合(类数组对象) 从整个文档获取
element.getElementsByClassName(className) // 从element的后代中获取
1.4 根据 name 属性值获取
正常的规范中,咱们只会给表单元素起name值,如果给其它元素设置name,在ie9以下版本浏览器不兼容,是获取不到的,
所以为了这种情况,咱们以后养成习惯,只给表单元素用name,非表单元素不用name
document.getElementsByName() //返回集合 只有document才有该方法
1.5 根据选择器获取
注意:querySelector 和querySelectorAll 在ie6-ie8 下不兼容
document.querySelector(选择器) //选择器第一个满足选择器条件的
document.querySelectorAll(选择器) //选择所有满足选择器条件的,返回nodeList(类数组对象)
element.querySelector(选择器)
element.querySelectorAll(选择器)
1.6 document.head
获取Head元素对象
1.7 document.body
获取body元素对象
1.8 document.documentElement
获取html元素对象
2、获取一屏幕的宽度或者高度,兼容所有的浏览器
// 获取一屏幕的高度
var vH = document.documentElement.clientHeight || document.body.clientHeight;
// 获取一屏幕的宽度
var vW = document.documentElement.clientWidth || document.body.clientWidth;
3、id小妙招
直接把id当成变量去用的时候,可以获取相应的id元素。(浏览器的机制)
<div id="box1">111</div>
<script>
console.log(box1)
</script>
2、节点
- 文档节点
- 属性节点
- 元素节点
- 文本节点
- 注释节点
2.1 文档节点
- nodeType(节点类型):9
- nodeName(节点名称):"#document"
- nodeValue(节点值):null
document.nodeType;
document.nodeName
document.nodeValue;
2.2 属性节点
- nodeType:2
- nodeName:属性名
- nodeValue:属性值
getAttributeNode() 方法从当前元素中通过名称获取属性节点。
<a href="http://www.baidu.com" id="a1">百度</a>
var a1=a1.getAttributeNode("href");// 获取属性节点
console.log(a1.nodeType);//2
console.log(a1.nodeName);//"href"; 属性名
console.log(a1.nodeValue);//"http://www.baidu.com"; 属性值
2.3 元素节点
- nodeType:1
- nodeName:大写的标签名
- nodeValue:null
<div id="box">百度</div>
<script>
console.log(box.nodeName)
</script>
2.4 文本节点
- nodeType:3
- nodeName:"#text"
- nodeValue:文本内容
- 在标准浏览器中,换行和空格也属于文本节点
<a href="http://www.baidu.com" id="a1">百度</a>
var res=a1.childNodes[0];
console.log(res.nodeType);//3
console.log(res.nodeValue);//"百度";
console.log(res.nodeName);//"#text";
2.5 注释节点
- nodeType:8
- nodeName:"#comment"
- nodeValue:注释的内容
<a href="http://www.baidu.com" id="a1">
<!--a标签 -->
百度
</a>
a1.childNodes; //NodeList(3) [text, comment, text]
a1.childNodes[1].nodeName;//"#comment"
a1.childNodes[1].nodeType;//8
a1.childNodes[1].nodeValue;//"a标签 "
3、节点之间关系的属性
节点类:
parentNode 父节点
childNodes 所有子节点的集合
firstChild 第一个子节点
lastChild 最后一个子节点
previousSibling 上一个兄弟节点
nextSibling 下一个兄弟节点
元素类:
children 所有子元素的集合
firstElementChild 第一个子元素 IE9+
lastElementChild 最后一个子元素 IE9+
previousElementSibling 上一个兄弟元素 IE9+
nextElementSibling 下一个兄弟元素 IE9+
3.1 parentNode
获取当前节点唯一的父亲节点
<div class="box333">
<div>
<!-- 111 -->
<div id="box">111</div>
</div>
</div>
<script>
console.log(box.parentNode)
</script>
3.2 childNodes
获取当前节点所有的子节点
3.3 firstChild
获取被选节点的第一个子节点。
<ul id="main">
<!-- 我是注释 -->
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
</ul>
<script>
console.log(main.firstChild);//#text
</script>
3.4 lastChild
获取被选节点的最后一个子节点。
<ul id="main">
<!-- 我是注释 -->
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
</ul>
<script>
console.log(main.lastChild);//#text
</script>
3.5 previousSibling
获取上一个哥哥节点
<ul id="main">
<!-- 我是注释 -->
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
</ul>
<script>
console.log(main.previousSibling);//#text
</script>
3.6 nextSibling
获取当前节点的下一个兄弟节点
<ul id="main">
<!-- 我是注释 -->
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
</ul><!-- 1111 -->
<script>
console.log(main.nextSibling);//<!-- 1111 -->
</script>
3.7 children
获取当前元素所有的元素子节点,但是在ie6--ie8下不兼容
<ul id="main">
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
</ul>
<script>
console.log(main.children);//HTMLCollection(4) [li, li, li, li]
</script>
3.8 firstElementChild
获取当前节点的第一个元素子节点 ie6-ie8 不兼容
<ul id="main">
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
</ul>
<script>
console.log(main.firstElementChild);
</script>
3.9 lastElementChild
获取当前节点的最后一个元素子节点 ie6-ie8 不兼容
<ul id="main">
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!111</li>
</ul>
<script>
console.log(main.lastElementChild);
</script>
3.10 previousElementSibling
获取上一个哥哥元素节点 ie6-ie8 不兼容
<div>1111</div>
<ul id="main">
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!111</li>
</ul>
<script>
console.log(main.previousElementSibling);
</script>
3.11 nextElementSibling
获取当前节点的下一个兄弟元素节点 ie6-ie8 不兼容
<div>1111</div>
<ul id="main">
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!</li>
<li>选择珠峰的,都是明智的!111</li>
</ul>
<script>
console.log(main.nextElementSibling);
</script>
练习题
自己手动封装一个获取节点下面的所有子元素,要求考虑兼容性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
</style>
</head>
<body>
<span id="span1">1</span>
<ul id="main">
<!-- 我是注释 -->
<li>选择A的,都是明智的!</li>
<li>选择A的,都是明智的!</li>
<li>选择A的,都是明智的!</li>
<li>选择A的,都是明智的!</li>
</ul>
<span>2</span>
</body>
</html>
<script>
function children(element){
var nodeLists=element.childNodes;
var result=[]
for(var i=0;i<nodeLists.length;i++){
nodeLists[i].nodeType===1?result.push(nodeLists[i]):null;
}
return result;
}
console.log(children(main));
</script>
自己手动封装一个previousElementSibling,要兼容。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
</style>
</head>
<body>
<span id="span1">1</span>
<ul id="main">
<!-- 我是注释 -->
<li>选择A的,都是明智的!</li>
<li>选择A的,都是明智的!</li>
<li>选择A的,都是明智的!</li>
<li>选择A的,都是明智的!</li>
</ul>
<span id="span2">2</span>
</body>
</html>
<script>
function previousElmentSibling(ele){
var pre=ele.previousSibling;
while(pre&&pre.nodeType!==1){
pre=pre.previousSibling;
}
return pre;
}
console.log(previousElmentSibling(span2))
</script>
DOM 的增删改
1、createElement:创建一个元素
document.createElement("div");
2、createTextNode: 创建一个文本节点
var otext=document.createTextNode("哈哈!");
3、appendChild:把元素追加到一个容器的末尾
语法:[context].appendChild([元素]);
<div id="id1"></div>
<script>
var odiv = document.createElement("div");
id1.appendChild(odiv);
console.log(id1)
</script>
4、insertBefore: 把一个元素插入到另一个元素的前面
首先要指定一个父节点
var insertedNode = 父节点.insertBefore(要插入的节点, 插在这个节点之前)
var insertedNode = parentNode.insertBefore(newNode, referenceNode)
- newNode:将要插入的节点
- referenceNode:被参照的节点(即要插在该节点之前)
- insertedNode:插入后的节点
- parentNode:父节点
<div id="id1">
<p class="p1" id="p1">这是P1</p>
</div>
<script>
var div = document.getElementById('id1');
var p1 = document.getElementById('p1');
var odiv = document.createElement("div");
var returnDom = div.insertBefore(odiv, p1);
console.log(div)
</script>
5、cloneNode:把某一个节点进行克隆
- 【ele】.cloneNode();浅克隆: 只是克隆了一个节点,里面的内容还有样式都没克隆
- 【ele】.cloneNode(true);深克隆:把节点包含的所有内容进行克隆
<div id="id1">
<p class="p1" id="p1">这是P1</p>
</div>
<script>
var res = id1.cloneNode();
var res2 = id1.cloneNode(true)
console.log(res)
console.log(res2)
</script>
6、removeChild:移除某个节点
【context】.removeChild(ele);
<div id="id1">
1111
<p class="p1" id="p1">这是P1</p>
</div>
<script>
id1.removeChild(p1);
console.log(id1)
</script>
7、set/get/removeAttribute
设置/获取/删除 当前元素的某一个自定义属性
- setAttribute
- getAttribute
- removeAttribute
box.setAttribute("index", 1);
box.getAttribute("index");
box.removeAttribute("index");
console.log(box)
// 设置
// box["aa"] = 22;
// 获取
// box["aa"]
//移除
// delete box["aa"];
基于键值对方式 增删改:修改当前对象的堆内存空间完成的(在堆内存空间可以看到)
基于Attribute dom方法增删改,是修改html结构来完成的(此种方法设置的在结构上可以看到)
以上两种方式不能混用
题目
利用a标签的href来重新获取url参数
var str = "珠峰培训-十二年专注前端培训,有口皆碑的前端培训机构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = "http://www.zhufengpeixun.cn?name=lili&age=18#123"
/*
search: "?name=lili&age=18"
hash: "#123"
*/
function queryParams(str) {
var a = document.createElement("a");
a.href = str;
var obj = {};
console.log(a.search); //?name=lili&age=18
console.log(a.hash); //#123
//[name=lili,age=18]
var search = a.search.substr(1);
console.log(search);//name=lili&age=18
obj.hash = a.hash ? a.hash : null;
if (search) {
var searchAry = search.split("&");
console.log(searchAry)// ['name=lili', 'age=18']
for (var i = 0; i < searchAry.length; i++) {
var itemAry = searchAry[i];//name=lili age=18
var item = itemAry.split("=");
console.log(item)//['name', 'lili']['age', '18']
var key = item[0];
var value = item[1];
obj[key] = value;
}
}
return obj;
}
var dd = queryParams(str);
console.log(dd)
</script>
</body>
</html>