DOM基础
Document Object Model,文档对象模型,主要目的就是把网页里面的元素当成对象一样来操作
DOM技术的本质操作我们的HTML元素进行各种格样的操作
DOM技术里面分两个部分,一个是JavaScript与html的结合,一个是JavaScript与css的结合
在学习之前,我们先简单了说明一下
1、document是文档的意思,因为文档指向的是当前网页,所以DOM在操作里面的整个页面的时候就会形成一个document的对象
2、页面上面所有的元素,最终会被转换成JavaScript里面的对象(所以我们操作标签对象就可以像操作之前我们学过的对象一样)
3、如果是非IE浏览器,它会根据每个ID生成一个对象,方便我们直接获取
通过JavaScript获取页面元素
首先再强调一遍,当前的页面指向的是document整个对象
1、通过ID来获取元素
document.getElementById("元素id属性值");
通过这种方式获取,永远只能获取到1个或0个(null)元素,不具备数据特性,如果找不到就返回null
2、通过class来获取元素
document.getElementsByClassName("类名");
通过这种方式,获取到一个叫做
HTMLCollection
的集合(类数组),具备数组特性,但是不具备数组方法,这个集合里面存放的都是DOM对象,如果一个都没获取到,返回一个空数组
3、通过标签名来获取
document.getELementsByTagName("标签名");
通过这种方式,获取到一个叫做
HTMLCollection
的集合(类数组),具备数组特性,但是不具备数组方法,这个集合里面存放的都是DOM对象,如果一个都没获取到,返回一个空数组
4、通过name属性来获取
document.getElementsByName("name属性值");
通过这种方式获取的是一个叫做
NodeList
集合,它也是一个类数组,具备数组特性但不具备数组方法,这个集合里面也存放的DOM对象,如果一个都获取不到返回空数组
上面4种方式是我们最基础的4种获取元素的方式,这种方法兼容性比较好,可以在绝大数浏览器种使用
如果页面的结构比较复杂的情况,我们要怎么获取
<div id="div1">
<div class="div2">
我爱北京天安门
</div>
<div class="div2">
天安门上太阳升
</div>
<div class="div3">
哈哈哈哈哈
</div>
</div>
<div class="div2">我是第二个盒子</div>
<div class="div2">我是第二个盒子的副本</div>
<p>我是一个段落标签</p>
<input type="radio" name="sex">男
<input type="radio" name="sex">女
在上面的网页结构种,如果我们想获取到id="div1"里面的class="div2"的元素怎么办?
//第一步,先获取div1这个元素
var div1 = document.getElementById("div1");
//第二步,在div1当中取div2元素,我们之前都在document当中去找,现在是在div1去找
var div2 = div1.getElementsByClassName("div2");
这是我们很早以前的解决方案,现在我们已经可以不使用这种方式,转而另寻新欢(强烈推荐)
新的方法主要是结合了HTML5和CSS3的东西,我们把CSS3当中9大选择器与之前的JavaScript做了结合
1、通过 querySelector()
来获取元素
document.querySelector("#div1"); //获取id为div1的元素
document.querySelector(".div2"); //获取类名为div2的元素
这种方法是通过选择器来选择元素,如果找到了元素就返回1个元素,找不到返回null,即使找到多个元素,也只返回1个元素
2、通过 querySelectorAll()
来获取元素s
document.querySelectorAll(".div2"); //找到所有类名为div2的元素,返回一个集合
document.querySelectorAll("#div1>.div2"); //返回id名为div1下一级的所有类名为div2的元素
这种方法也是通过指定的选择器来获取元素,它返回的是一个NodeList的类数组,里面包含了要查找的元素,如果找不到返回一个空数组
总结: getElementById与querySelector都是返回1个或者null,找到就只返回1个,找不到返回null
querySelectorAll和后面getElementsBy *** 都是返回一个集合
DOM的结构
DOM本身也是一个对象,我们以前也叫过对象都有自己的属性和方法
我们来分析一下DOM对象
标签名 | 第一级 | 第二级 | 第三级 | 第四级 | 第五级 |
---|---|---|---|---|---|
div | HTMLDivElement | HTMLElement | Element | Node | EventTarget |
p | HTMLParagraphElement | HTMLElement | Element | Node | EventTarget |
通过上面的两种标签对象的对比分析,我们可以看到所有的元素最终都继承自Node对象(EventTarget对象暂时先不管),我们可以把Node当成所有页面元素对象的父级,这个时候如果我们弄清除了Node对象,我们其实也就搞清除上面的元素对象
Element与Node区别
<div id="div1">
我在前面插入了一段文字
<div class="div2">第一行</div>
<div class="div2">第二行</div>
<!-- 我是一个注释 -->
</div>
1、网页当中的所有标签都可以是一个元素(element),同时也可以是一个节点node
2、但并不是所有的节点Node都是一个元素Element(节点是包含了元素,文字,注释,回车)
在上面的网页结构种,div1里面的所有就仅仅只有div2这两个,但是它的节点就很多了
Element常用属性
Element指的是页面上面的标签所形成的元素,我们学习属性和方法就是为了去操作HTML元素的
1、children属性,获取当前元素下面的子元素,它会返回一个HTMLCollection的集合
到目前为止,我们有三种可以获得子元素的方式
//第一种方式
var ul1 = document.getElementById("ul1");
var li1 =ul1.getElementsByTagName("li");
//第二种方式
var lis =document.querySelectorAll("#ul1>li");
//第三种方式
var ul1 = document.querySelector("#ul1");
ul1.children;
上面三种方式,各自有各自的好处不好一概而论,前面两种都有一个问题就是不能找到父级,只能找同级或者子级
,而第三种方式,为我们提供了一个思路,既然能children这个属性,那么是否可以有其他的属性去找全家,第三种在JavaScript中提供了一整套获取元素的体系
2、parentElement
,获取当前元素的父级元素
3、nextElementSibling
,获取当前元素的下一个兄弟元素
4、previousElementSibling
获取当前元素的上一个兄弟元素
前面4个属性就是以当前元素为中心去获取父级,子级,前一个,后一个元素
5、className
属性,获取或设置当前元素的class属性(类名)
<div id="div1">
<div class="div2">
我爱北京天安门
</div>
<div class="div2">
天安门上太阳升
</div>
<div class="div3">
哈哈哈哈哈
</div>
</div>
<div class="div2">我是第二个盒子</div>
<div class="div2">我是第二个盒子的副本</div>
<p>我是一个段落标签</p>
<input type="radio" name="sex">男
<input type="radio" name="sex">女
<script type="text/javascript">
var div1 = document.querySelector("#div1");
div1.children[0].className = "box";
</script>
通过上面的例子我们现在就已经可以操作元素的样式了,但是工作中实际中我们不这么干,因为会有问题
6、classList
属性 ,返回当前元素的class类名的集合,它返回的是一个叫做DOMTokenList对象(类数组),
这个集合里面包含了所有的class类名
-
add()
方法,在当前元素的classList里面添加一个class -
div1.classList.add("p3");
-
remove()
方法,跟当前的classList里面删除一个class -
div1.classList.remove("p1");
-
toggle()
方法,如果classList当前有这个类名就删除,如果过没有就添加 -
div1.classList.toggle("p1");
-
contains()
方法,判断当前的classList中是否有这个类名,如果有则返回true,没有返回false
7、firstElementChild
属性,获取当前元素下的第一个子元素,相当于 children[0]
8、lastElementChild
属性,获取当前元素下的最后一个子元素
9、innerText
属性,获取或设置当前元素的文本内容,如果赋值的时候是HTML标签,那么依然会以文本的形式进行赋值,不会进行html转义
<div class="box">我是一个盒子</div>
<script type="text/javascript">
var box = document.querySelector(".box");
box.innerText = "<h1>我是爸爸</h1>"; //h1标签会被直接输出到页面内容上面
</script>
10、innerHTML
属性,获取或设置当前元素的HTML内容 ,如果过赋值的时候是HTML你标签,那么会对标签的部分进行转义
<div class="box">我是一个盒子</div>
<script type="text/javascript">
var box = document.querySelector(".box");
box.innerHTML = "<h1>我是爸爸</h1>"; //h1标签会被当前标签渲染出来
</script>
11、tagName
属性,返回当前元素的标签名(返回的是大写标签名)
12、value
属性,它是表单标签才会有的属性,可以对这个属性取值赋值
13、childElementCount
获取当前元素子元素的个数
Element常用方法
1、createElement()
方法,根据标签名创建一个标签元素
var div1 = document.createElement("div");
var p1 = document.createElement("p");
2、appendChild()
方法,向当前元素里面的最后去追加一个新的元素
div1.appendChild(p1); //将p1追加到div1标签的内部的最后
document.body.appendChild(div1); //再将div1追加到网页的body标签里面
3、remove()
方法,删除当前的元素(里面的子元素也会一并被删除)
4、removeChild()
方法,删除指定的子元素,返回这个删除的子元素
ul1.children[1].remove();
ul1.removeChild(ul1.children[1]);
5、cloneNode()
克隆一个相同的元素出来,它接收一个参数,是布尔类型,默认是false,如果传一个true,则代表要克隆子元素
var ul2 = ul1.cloneNode(); //只克隆当前元素
var ul3 = ul1.cloneNode(true); //克隆当前的元素和所有的子元素
6、insertAdjacentElement()
方法,在指定位置插入元素
var ul3 = ul1.cloneNode(true); ul1.insertAdjacentElement("beforeEnd",ul3);
参数值 | 解释 |
---|---|
beforeBegin | 开始标签之前 |
afterBegin | 开始标签之后 |
beforeEnd | 结束标签之前 |
afterEnd | 结束标签之后 |
除了有 insertAdjacentElement
方法插入元素以外,还有其他与它类似的方法
insertAdjacentHTML()
插入网页标签
insertAdjacentText()
插入文本
var p1 = "<p>我是一个p标签</p>";
ul1.insertAdjacentHTML("beforeBegin",p1); //与innerHTML类似
ul1.insertAdjacentText("beforeBegin",p1); //与innerText类似
HTMLCollection与NodeList的区别
我们之前讲过元素的获取,我们通过 document.getElementsByTagName
获取到是元素的一个 HTMLCollection
的集合,而通过 document.getElementsByName/document.querySelectorAll
获取的集合是一个 NodeList
的集合,那么这两种集合有什么区别?
<ul class="ul1">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script>
// 要求删除掉ul1内部的所有li元素
</script>
现在有上面的代码,我们如果要删除这里ul1内部所有的li,首先就应该先获取到里面的所有li,然后去调用 remove()
方法去删除
第一种方式获取li
var ul1 = document.querySelector(".ul1");
var list1 = ul1.children; //这个时候list1就是一个HTMLCollection集合
for(var i = 0;i < list1.length ;i++){
list1[i].remove();
}
这个时候我们会还想,并没有完全删掉里面的li,因为它是一个动态的集合,它的索引会发现变化,长度也会发生变化,这种现象我们叫沙漏效应,对应这种情况,我们可以采取倒序的方式去删除
for(var i = list1.length - 1; i >= 0; i--){
list1[i].remove();
}
第二种方式获取li
var ul1 = document.querySelectorAll(".ul1>li"); //这个时候ul1就是一个NodeList集合
for(var i = 0;i < ul1.length ;i++){
ul1[i].remove();
}
这个时候我们就发现li都被删除完了,说明 NodeList
并没有形成一个沙漏效应
HTMLCollection
是一个动态集合,而 NodeList
是一个静态集合
通过上面的演示元素的删除,其实就可以看作是HTMLCollection与NodeList的区别,包括在添加的时候也是一样的