1.DOM概念
文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口。在网页上,组织页面(或文档)的对象被组织在一个树形结构中,用来表示文档中对象的标准模型就称为DOM。
DOM又称为文档树模型:
- 文档:一个网页可以称为文档
- 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
- 元素:网页中的标签
- 属性:标签的属性
DOM经常进行的操作:
- 获取元素
- 对元素进行操作(设置其属性或调用其方法)
- 动态创建元素
- 事件(什么时机做相应的操作)
2.获取页面元素
- 根据id获取元素(返回值是一个元素对象)
let btn=document.getElementById("btn");
console.log(btn);
- 根据标签名获取元素(返回值是一个伪数组)
let ps=document.getElementsByTagName("p")
for(let i=0;i<ps.length;i++){
console.log(ps[i]);
}
- 根据name获取元素(返回值是一个伪数组)
var inputs = document.getElementsByName('hobby');
for (let i = 0; i < inputs.length; i++) {
console.log(inputs[i]);
}
- 根据类名获取元素
var clsList= document.getElementsByClassName('cls');
for (let i = 0; i < clsList.length; i++) {
console.log(clsList[i]);
}
- 根据选择器获取元素
console.log(document.querySelector("p"));//只能获取第一个p标签
console.log(document.querySelectorAll("p"));//获取所有的p标签对象
console.log(document.querySelector('#text'));//获取id为text的元素
console.log(document.querySelectorAll('.box'));//获取所有类名为box的元素
3.属性操作
【1】非表单元素的属性:href、title、id、src、className
案例:
let link = document.getElementById('link');
console.log(link.href);
console.log(link.title);
let pic = document.getElementById('pic');
console.log(pic.src);
案例:
//一个简单的网页开关灯
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.cls{
background-color: black;
}
</style>
</head>
<body>
<input type="button" value="开/关灯" id="btn">
<script>
function my$(id){
return document.getElementById(id);
}
my$("btn").onclick=function(){
document.body.className=document.body.className==="cls"?"":"cls";
}
</script>
</body>
</html>
- textContent 设置标签中的文本内容,应该使用textContent属性,谷歌,火狐支持,IE8不支持
- innerText 主要是设置文本的,设置标签内容,是没有标签的效果的。可以获取标签中间的文本内容,但是标签中如果还有标签,那么最里面的标签的文本内容也能获取。在谷歌、火狐和IE8中都可以使用,但是在低版本的狐火中可能不兼容
- innerHTML 是可以设置文本内容,但是主要的作用是在标签中设置新的html标签内容,是有标签效果的。真正的获取标签中间的所有内容(包括标签)
总结:想要设置标签内容,使用innerHTML,想要设置文本内容,innerText或者textContent,或者innerHTML,推荐用innerHTML。
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
width: 300px;
height: 300px;
border: 2px solid gray;
margin-top: 10px;
}
</style>
</head>
<body>
<input type="button" value="按钮" id="btn">
<div>春有百花秋有月</div>
<script>
//textContent --在谷歌、火狐中可以使用,但是不兼容IE8
//innerText --在谷歌、火狐和IE8中都可以使用,但是在低版本的狐火中可能不兼容
//因此可以封装这两个方法,已兼容火狐和IE
//设置文本内容
function setInnerText(element,text){
if(element.textContent){//不支持textContent
element.innerText=text;
}else{
element.textContent=text;
}
}
//获取文本内容
function getInnerText(element){
if(element.textContent){
return element.innerText;
}else{
return element.textContent;
}
}
document.getElementById("btn").onclick=function(){
console.log(getInnerText(document.getElementsByTagName("div")[0]));
setInnerText(document.getElementsByTagName("div")[0],"春有百花秋有月,夏有凉风冬有雪")
}
</script>
</body>
</html>
【2】表单元素属性
- value 用于大部分表单元素的内容获取(option除外)
- type 可以获取input标签的类型(输入框或复选框等)
- disabled 禁用属性
- checked 复选框选中属性
- selected 下拉菜单选中属性
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="嘿,没点~">
<input type="button" value="嘿,没点~">
<input type="button" value="嘿,没点~">
<input type="button" value="嘿,没点~">
<input type="button" value="嘿,没点~">
<input type="button" value="嘿,没点~">
<script>
let btnObjs=document.getElementsByTagName("input");
for(let i=0;i<btnObjs.length;i++){
btnObjs[i].onclick=function(){
//把所有的设置为没点
for(let j=0;j<btnObjs.length;j++){
btnObjs[j].value="嘿,没点~"
}
//把当前点击的按钮设置为点了
this.value="哟呵,点了!"
}
}
</script>
</body>
</html>
【3】自定义属性操作
- getAttribute() 获取标签行内属性
- setAttribute() 设置标签行内属性
- removeAttribute() 移除标签行内属性
- 与element.属性的区别: 上述三个方法用于获取任意的行内属性。
案例:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style-type: none;
}
.box {
width: 400px;
height: 300px;
border: 1px solid #ccc;
margin: 100px auto;
overflow: hidden;
}
.hd {
height: 45px;
}
.hd span {
display: inline-block;
width: 90px;
background-color: pink;
line-height: 45px;
text-align: center;
cursor: pointer;
}
.hd span.current {
background-color: purple;
}
.bd li {
height: 255px;
background-color: purple;
display: none;
}
.bd li.current {
display: block;
}
</style>
</head>
<body>
<div class="box" id="box">
<div class="hd">
<span class="current">体育</span>
<span>娱乐</span>
<span>新闻</span>
<span>综合</span>
</div>
<div class="bd">
<ul>
<li class="current">我是体育模块</li>
<li>我是娱乐模块</li>
<li>我是新闻模块</li>
<li>我是综合模块</li>
</ul>
</div>
</div>
<script>
//获取hd的spanlist
let hd=document.getElementsByClassName("hd")[0];
let spanList=hd.getElementsByTagName("span");
//获取bd的li list
let bd=document.getElementsByClassName("bd")[0];
let liList=document.getElementsByTagName("li");
for(let i=0;i<spanList.length;i++){
spanList[i].setAttribute("index",i);
spanList[i].onclick=function(){
for(let j=0;j<spanList.length;j++){
spanList[j].removeAttribute("class");
}
this.className="current";
for(let j=0;j<liList.length;j++){
liList[j].removeAttribute("class");
}
liList[this.getAttribute("index")].className="current";
}
}
</script>
</body>
</html>
4.创建元素的三种方式
- 【1】document.write()
需注意:在页面加载完之后调用document.write() 创建元素时,此时原页面的所有元素都会被干掉,只存在这个创建的元素。
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="create p" id="btn">
<script>
//document.write
//在页面加载完之后调用document.write() 创建元素时,此时原页面的所有元素都会被干掉,只存在这个创建的元素。
//而如果是在页面加载时创建的,就没有这个问题。
document.getElementById("btn").onclick=function () {
document.write("<p>这是一个p标签</p>");
}
</script>
</body>
</html>
- 【2】innerHTML
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
width: 200px;
height: 200px;
border: 1px solid red;
}
</style>
</head>
<body>
<input type="button" value="创建" id="btn">
<div id="dv"></div>
<script>
//第二种创建元素的方式
//对象.innerHtml=""
document.getElementById("btn").onclick=function () {
// body...
document.getElementById("dv").innerHTML="<p>春有百花秋有月,夏有凉风冬有雪。若无闲事挂心头,便是人间好时节。</p>";
}
</script>
</body>
</html>
- 【3】document.createElement()
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
div{
width: 300px;
height: 300px;
border: 1px dotted pink;
margin-top: 10px;
}
</style>
</head>
<body>
<input type="button" value="按钮" id="btn">
<div id="dv"></div>
<script src="L114 common.js"></script>
<script>
//document.createElement("标签名");
document.getElementById("btn").onclick=function () {
// body...
//只创建了元素没有说把这个元素放在哪里
let pObj=document.createElement("p");//创建了p标签
setInnerText(pObj,"春有百花秋有月,夏有凉风冬有雪。若无闲事挂心头,便是人间好时节。");//设置元素内容
//追加到父元素中
document.getElementById("dv").appendChild(pObj);
}
</script>
</body>
</html>
5.节点操作
-
节点的相关属性:
nodeType —节点类型:1—标签;2—属性;3—文本
nodeName —节点的名字: 标签节点-大写的标签名字;属性节点-小写的属性名;文本节点—#text
nodeValue–节点的值:标签节点–null;属性节点–属性值;文本节点–文本的内容 -
获取父节点、父元素
//父级节点
console.log(ulObj.parentNode);
//父级元素
console.log(ulObj.parentElement);
- 获取子节点、子元素
//子级节点
console.log(ulObj.childNodes);
//子级元素
console.log(ulObj.children);
- 获取第一个子节点、第一个子元素
//第一个子节点
console.log(ulObj.firstChild);
//第一个子元素
console.log(ulObj.firstElementChild);
- 获取最后一个子节点、最后一个子元素
//最后一个子节点
console.log(ulObj.lastChild);
//最后一个子元素
console.log(ulObj.lastElementChild)
- 获取前一个兄弟节点、前一个兄弟元素
//上一个兄弟节点
console.log(threeObj.previousSibling)
//上一个兄弟元素
console.log(threeObj.previousElementSibling);
- 获取下一个兄弟节点、下一个兄弟元素
//下一个兄弟节点
console.log(threeObj.nextSibling);
//下一个兄弟元素
console.log(threeObj.nextElementSibling)
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="隔行变色" id="btn">
<ul>
<li>奔驰</li>
<li>宝马</li>
<li>奥迪</li>
<li>特斯拉</li>
<li>布加迪</li>
<li>保时捷</li>
<li>玛莎拉蒂</li>
<li>劳斯莱斯</li>
</ul>
<script>
document.getElementById("btn").onclick=function(){
let nodes=document.getElementsByTagName("ul")[0].childNodes;
let count=0;
for(let i=0;i<nodes.length;i++){
if(nodes[i].nodeType===1 && nodes[i].nodeName==="LI"){
nodes[i].style.backgroundColor= count%2===0?"red":"yellow";
count++
}
}
}
</script>
</body>
</html>
6.事件
事件:触发-响应机制
【1】事件三要素
- 事件源:触发(被)事件的元素
- 事件类型:事件的触发方式(例如鼠标点击或键盘点击)
- 事件处理程序:事件触发后要执行的代码(函数形式)
【2】注册/移除事件的三种方式
- 对象.on事件类型=事件处理函数
如果是多个相同事件注册用这种方式,最后一个执行,之前的被覆盖了
//绑定事件
var btnObj= document.getElementById('btn');
btnObj.onclick = function () {
console.log('点击后执行');
};
//解绑事件
btnObj.onclick = null;
- 对象.addEventListener(“没有on的事件类型”,事件处理函数,false)
谷歌,火狐,IE11支持,IE8不支持
最后的参数false表示在冒泡阶段,若为true表示在捕获阶段
//绑定事件
btnObj.addEventListener('click', fn, false);
//解除绑定
btnObj.removeEventListener('click', fn, false);
- 对象.attachEvent(“有on的事件类型”,事件处理函数)
谷歌火狐不支持,IE11不支持,IE8支持
//绑定事件
btnObj.attachEvent('onclick', fn);
//解除绑定
btnObj.detachEvent('onclick', fn);
案例:为元素绑定事件、解除绑定事件的兼容代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="button" value="我是绑定按钮" id="btn">
<input type="button" value="我是解绑按钮" id="btn2">
<script>
function my$(id) {
return document.getElementById(id);
}
//绑定事件兼容代码
function addEventListener(element,type,fn) {
if(element.addEventListener){
element.addEventListener(type,fn,false);
}else if(element.attachEvent){
element.attachEvent("on"+type,fn);
}else{
element["on"+type]=fn;
}
}
//解绑事件兼容代码
function removeEventListener(element,type,fn) {
if(element.removeEventListener){
element.removeEventListener(type,fn,false);
}else if(element.detachEvent){
element.detachEvent("on"+type,fn);
}else{
element["on"+type]=null;
}
}
//测试
function f1() {
console.log("第一个事件")
}
function f2() {
console.log("第二个事件")
}
function f3() {
console.log("第3个事件")
}
addEventListener(my$("btn"),"click",f1);
addEventListener(my$("btn"),"click",f2);
addEventListener(my$("btn"),"click",f3);
my$("btn2").onclick=function(){
removeEventListener(my$("btn"),"click",f1);
}
</script>
</body>
</html>
【3】事件的三个阶段
- 1.捕获阶段 —使用 对象.eventPhase —值为1表示捕获阶段 ----捕获阶段从外到内
- 2.目标阶段 —使用 对象.eventPhase —值为2表示目标阶段
- 3.冒泡阶段 —使用 对象.eventPhase —值为3表示冒泡阶段 ----冒泡阶段从内到外
事件冒泡:有多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的事件触发了,那么外面的事件也自动触发了。如下案例:点击最小的蓝色div,外层的所有点击事件也都会触发。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#dv4{
width: 400px;
height: 400px;
background-color: pink;
}
#dv3{
width: 300px;
height: 300px;
background-color: yellow;
}
#dv2{
width: 200px;
height: 200px;
background-color: green;
}
#dv1{
width: 100px;
height: 100px;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="dv4">
<div id="dv3">
<div id="dv2">
<div id="dv1"></div>
</div>
</div>
</div>
<script>
//事件冒泡:有多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的事件触发了,那么外面的事件也自动触发了
//阻止事件冒泡
//1.window.event.cancelBubble=true =======IE 谷歌支持 火狐不支持
//2. e.stopPropagation() ---谷歌 火狐支持 IE不支持
//事件的三个阶段
//1.捕获阶段 ---使用eventPhase ---值为1表示捕获阶段 ----捕获阶段从外到内
//2.目标阶段 ---使用eventPhase ---值为2表示目标阶段
//3.冒泡阶段 ---使用eventPhase ---值为3表示冒泡阶段 ----冒泡阶段从内到外
//使用 addEventListener(事件类型,事件处理函数,boolean) ----boolean --false 为冒泡阶段 ---true 为捕获阶段
function my$(id) {
return document.getElementById(id);
}
let dvObjs=[my$("dv1"),my$("dv2"),my$("dv3"),my$("dv4")];
dvObjs.forEach(function (ele,index) {
ele.addEventListener("click",function (e) {
console.log(this.id+"======事件阶段为:"+e.eventPhase);
},false)
});
// my$("dv1").οnclick=function (e) {
// console.log(this.id);
// // window.event.cancelBubble=true;
// e.stopPropagation();
// }
// my$("dv2").οnclick=function () {
// console.log(this.id);
// }
// my$("dv3").οnclick=function () {
// console.log(this.id);
// }
// my$("dv4").οnclick=function () {
// console.log(this.id);
// }
</script>
</body>
</html>
阻止事件冒泡:
(1).window.event.cancelBubble=true IE 谷歌支持 火狐不支持
(2).e.stopPropagation() <font color=#5c7a29 谷歌 火狐支持 IE不支持