一, DOM树介绍
DOM:文档对象模型。DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
DOM就是由节点组成的:HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树。
在HTML当中,一切都是节点:
- 元素节点:HTML标签
- 文本节点:标签中的文字(比如标签之间的空格、换行)
- 属性节点::标签的属性
整个html文档就是一个文档节点。所有的节点都是Object。
利用DOM可以完成:
- 找对象(元素节点)
- 设置元素的属性值
- 设置元素的样式
- 动态创建和删除元素
- 事件的触发响应:事件源、事件、事件的驱动程序
二, 节点的查找
一, 直接查找
DOM节点的获取方式其实就是获取事件源的方式
操作元素节点,必须首先找到该节点。有三种方式可以获取DOM节点:
<!--示例数据--> <body> <div id = 'foo'> <div id = 'son1' class="son"> <img src="" alt=""> </div> <div id = 'son2' class="son"> <a href="http://www.baidu.com" id="baidu">百度</a> </div> </div> </body>
<script> //方式一:通过id获取单个标签 var div_foo = document.getElementById('foo'); //方式二:通过标签名获得标签数组 var arr_div = document.getElementsByTagName('div'); //方式三:通过类名获得标签数组 var arr_son = document.getElementsByClassName('son'); //其中方式二、方式三获取的是标签数组,那么习惯性是先遍历之后再使用 </script>
二, 间接查找
DOM的节点并不是孤立的,因此可以通过DOM节点之间的相对关系对它们进行访问。如下:
节点的访问关系,是以属性的方式存在的。
JS中的父子兄访问关系:
获取父节点:
var son1 = document.getElementById('son1'); var foo = son1.parentNode;
获取兄弟节点:
下一个兄弟节点:
var son1 = document.getElementById('son1'); var son2 = son1.nextElementSibling;
上一个兄弟节点:
var son2 = document.getElementById('son2'); var son1 = son2.previousElementSibling;
获得任意一个兄弟节点:
var son1 = document.getElementById('son1'); var son = son1.parentNode.children[index];
获取子节点:
获取单个子元素节点:
获取第一个子元素节点:
var foo = document.getElementById('foo'); var son1 = foo.firstElementChild;
获取最后一个子元素节点:
var foo = document.getElementById('foo'); var son_last = foo.lastElementChild;
获取所有子元素节点:
var foo = document.getElementById('foo'); var arr_son = foo.children;
三, 节点操作
节点的访问关系都是属性。而节点的操作都是函数(方法
一, 节点本身的操作
创建节点
新的标签(元素节点) = document.createElement("标签名");
var a = document.createElement('a');
插入节点
父节点.appendChild(新的子节点);//方式1:父节点的最后插入一个新的子节点 父节点.insertBefore(新的子节点,作为参考的子节点);//方式2:在参考节点前插入一个新的节点。如果参考节点为null,那么他将在父节点最后插入一个子节点
删除节点
父节点.removeChild(子节点);//用父节点删除子节点。必须要指定是删除哪个子节点。 node1.parentNode.removeChild(node1);//删除自己这个节点
复制节点(克隆节点)
节点.cloneNode() //只克隆一层 节点.cloneNode(true) //克隆自己和所有的子子孙孙 注意 :如果克隆出来的标签的id是重复的,那么修改之后才能应用到页面上
替换节点
父节点.replaceChild(新标签,旧节点)
二, 节点属性的操作
示例数据:
<img src="img/timg.jpg" class="image-box" title="美女图片" alt="地铁一瞥" id="a1">
获取节点的属性值:
方式一
元素节点.属性; 元素节点[属性];
<body> <img src="images/1.jpg" class="image-box" title="美女图片" alt="地铁一瞥" id="a1"> <script type="text/javascript"> var myNode = document.getElementsByTagName("img")[0]; console.log(myNode.src); console.log(myNode.className); //注意,是className,不是class console.log(myNode.title); console.log("------------"); console.log(myNode["src"]); console.log(myNode["className"]); //注意,是className,不是class console.log(myNode["title"]); </script> </body>
方式二: 推荐使用
元素节点.getAttribute("属性名称");
console.log(myNode.getAttribute("src")); console.log(myNode.getAttribute("class")); //注意是class console.log(myNode.getAttribute("title"));
方式1和方式2的区别在于:前者是直接操作标签,后者是把标签作为DOM节点
设置节点的属性值:
方式一
myNode.src = "images/2.jpg" //修改src的属性值 myNode.className = "image2-box"; //修改class的name
方式二: 推荐
元素节点.setAttribute(属性名, 新的属性值);
myNode.setAttribute("src","images/3.jpg"); myNode.setAttribute("class","image3-box"); myNode.setAttribute("id","你好");
删除节点属性:
元素节点.removeAttribute(属性名);
myNode.removeAttribute("class"); myNode.removeAttribute("id");
三, 节点文本操作
获取文本节点的值:
var div = document.getElementById("d1") div.innerText # 获取该标签和内部所有标签的文本内容 div.innerHTML # 获取的是该标签内的所有内容,包括文本和标签
设置文本节点的值:
var div = document.getElementById("d1") div.innerText="1" # 只能设置文本 div.innerHTML="<p>2</p>" # 能识别成一个p标签
获取值操作:
标签.value--适用于以下标签,用户输入或者选择类型的标签:input 、select 、textarea
var iEle = document.getElementById("i1"); console.log(iEle.value); var sEle = document.getElementById("s1"); console.log(sEle.value); var tEle = document.getElementById("t1"); console.log(tEle.value);
class的操作:
className 获取所有样式类名(字符串) 首先获取标签对象 标签对象.classList.remove(cls) 删除指定类 classList.add(cls) 添加类 classList.contains(cls) 存在返回true,否则返回false classList.toggle(cls) 存在就删除,否则添加,toggle的意思是切换,有了就给你删除,如果没有就给你加一个
指定CSS操作:
obj.style.backgroundColor="red"
对于没有-的CSS属性一般直接使用style.属性名即可。如:margin
obj.style.margin obj.style.width obj.style.left obj.style.position
对含有-的CSS属性,将中横线后面的第一个字母换成大写即可。如:margin-top
obj.style.marginTop obj.style.borderLeftWidth obj.style.zIndex obj.style.fontFamily
四, 事件
JS是以事件驱动为核心的一门语言,事件的三要素:
- 事件源: 引发后续事件的html标签
- 事件: JS中定义的一些列事件
- 事件驱动程序: 对样式和html的操作,也就是DOM
代码书写步骤:
- 获取事件源: 节点的查找
- 绑定事件:
事件源box.事件onclick = function(){ 事件驱动程序 };
- 书写事件驱动程序: 关于DOM的操作
代码举例:
</head> <body> <button id="btn">点击一下</button> </body> <script> // 1. 获取事件源 var btn = document.getElementById('btn') // 2. 绑定事件 btn.onclick = function () { // 3. 书写事件驱动程序 alert('点我干啥!') } </script>
常见事件如下:
事件名 | 说明 |
---|---|
onclick | 鼠标单击 |
ondblclick | 鼠标双击 |
onkeyup | 按下并释放键盘上的一个键时触发 |
onchange | 文本内容或下拉菜单的选项发生改变 |
onfocus | 获得焦点,表示文本框等获得鼠标光标 |
onblur | 失去焦点,表示文本框等失去鼠标光标 |
onmouseover | 鼠标悬停,即鼠标停留在图片等的上方 |
onmouseout | 鼠标移出,即离开图片等所在的区域 |
onload | 网页文档加载事件 |
onnuload | 关闭网页时 |
onsubmit | 表单提交事件 |
onreset | 重置表单时 |
onscroll | 滚动轴移动事件 |
一, 绑定事件的方式
直接绑定匿名函数:
</head> <body> <button id="btn">点击一下</button> </body> <script> // 1. 获取事件源 var btn = document.getElementById('btn') // 2. 绑定事件 btn.onclick = function () { // 3. 书写事件驱动程序 alert('点我干啥!') } </script>
先单独定义函数,再绑定:
</head> <body> <button id="btn">点击一下</button> </body> <script> // 1. 获取事件源 var btn = document.getElementById('btn') // 2. 绑定事件 btn.onclick = fun; //注意没有() // 3. 书写事件驱动程序 function fun() { alert('点我干啥!') } </script>
行内绑定:
</head> <body> <button id="btn" onclick="fn()">点击一下</button> //注意时"fn()" </body> <script> function fun() { alert('点我干啥!') } </script>
二, 事件驱动程序
还可以操作标签的属性和样式,代码示例:
<head> <meta charset="UTF-8"> <title>Title</title> <style> #box{ width: 100px; height: 100px; background-color: yellow; /*使其变得可点击*/ cursor: pointer; } </style> </head> <body> <div id="box"></div> </body> <script> var box = document.getElementById('box'); box.onclick = function(){ this.style.width = '200px'; this.style.height = '200px'; this.style.backgroundColor = 'red'; } </script>
注意:
- 在JS中写属性值时,要用引号
- 在js里写属性名时,是
backgroundColor
,不是CSS里面的background-Color
.所有的像css属性的text-*
,line-*
、backgroun-*
等在js中都写成驼峰
三, 事件举例与练习
onload事件:
当页面加载(文本和图片)完毕的时候,触发onload事件
代码示例:
<script> window.onload = function () { alert('页面加载完毕!') } </script>
注意: js的加载是和html同步加载的.因此,如果使用元素在定义元素之前,容易报错.这个时候,onload事件就能派上用场了,可以把使用元素的代码放在onload里,就能保证这段代码是最后执行.
建议是: 整个页面上所有元素加载完毕再执行js内容.所以,window.onload可以预防使用标签在定义标签之前
应用之--获取可视区域大小:
<script type="text/javascript"> // 屏幕的可视区域 window.onload = function(){ // document.documentElement 获取的是html标签 console.log(document.documentElement.clientWidth); console.log(document.documentElement.clientHeight); // 窗口大小发生变化时,会调用此方法 window.onresize = function(){ console.log(document.documentElement.clientWidth); console.log(document.documentElement.clientHeight); } } </script>
应用之--offset系列:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>示例</title> <style type="text/css"> *{ padding: 0; margin: 0; } </style> </head> <body style="height: 2000px"> <div> <div class="wrap" style=" width: 300px;height: 300px;background-color: green"> <div id="box" style="width: 200px;height: 200px;border: 5px solid red;position: absolute;top:50px;left: 30px;"> </div> </div> </div> </body> <script type="text/javascript"> window.onload = function(){ var box = document.getElementById('box'); /* offsetWidth占位宽 内容+padding+border offsetHeight占位高 内容+padding+border offsetTop: 如果盒子没有设置定位 到body的顶部的距离,如果盒子设置定位,那么是以父辈为基准的top值 offsetLeft: 如果盒子没有设置定位 到body的左部的距离,如果盒子设置定位,那么是以父辈为基准的left值 */ console.log(box.offsetTop); console.log(box.offsetLeft); console.log(box.offsetWidth); console.log(box.offsetHeight); } </script> </html>
onscroll事件:
window.onscoll 在页面的滚动条滚动的时候触发的事件 document.documentElement.scrollTop
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>示例</title> <style> *{ padding: 0; margin: 0; } </style> </head> <body style="width: 2000px;height: 2000px;"> <div style="height: 200px;background-color: red;"></div> <div style="height: 200px;background-color: green;"></div> <div style="height: 200px;background-color: yellow;"></div> <div style="height: 200px;background-color: blue;"></div> <div style="height: 200px;background-color: gray;"></div> <div id = 'scroll' style="width: 200px;height: 200px;border: 1px solid red;overflow: auto;padding: 10px;margin-top: 5px;"> <p>我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码我是一段示例代码 </p> </div> </body> <script type="text/javascript"> window.onload = function(){ //实施监听滚动事件 window.onscroll = function(){ console.log('上'+document.documentElement.scrollTop); console.log('左'+document.documentElement.scrollLeft); console.log('宽'+document.documentElement.scrollWidth); console.log('高'+document.documentElement.scrollHeight); }; var s = document.getElementById('scroll'); s.onscroll = function(){ //scrollHeight : 内容的高度+padding 不包含边框 console.log('text上'+s.scrollTop); console.log('text左'+s.scrollLeft); console.log('text宽'+s.scrollWidth); console.log('text高'+s.scrollHeight); } } </script> </html>
红绿灯:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>红绿灯</title> <style> *{ padding: 0; margin: 0; } .clearfix:after{ content: ''; display: block; clear: both; } .foo{ border: solid 5px #b0b0b0; border-radius: 50px; float: left; } .son{ width: 100px; height: 100px; background-color: #b0b0b0; border-radius: 50px; float: left; } .red{ background-color: red; } .green{ background-color: green; } .yellow{ background-color: yellow; } </style> </head> <body> <div class="foofoo clearfix"> <div class="foo"> <div class="son red"></div> <div class="son"></div> <div class="son"></div> </div> </div> </body> <script> setInterval(fun, 2000); function fun(){ var foo = document.getElementsByClassName('foo')[0]; if (foo.children[0].classList.contains('red')){ foo.children[0].classList.remove('red'); foo.children[1].classList.add('green'); }else if (foo.children[1].classList.contains('green')){ foo.children[1].classList.remove('green'); foo.children[2].classList.add('yellow'); }else { foo.children[2].classList.remove('yellow'); foo.children[0].classList.add('red'); } } </script> </html>
input框动态显示时间:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动态显示时间</title> </head> <body> <input type="text" id="date"> <button id="control">开始</button> </body> <script> function update() { var date_s = document.getElementById('date'); var now_time = new Date().toLocaleString(); date_s.value = now_time; } var control = document.getElementById('control'); control.onclick = function () { switch (this.innerText) { case '开始': work = setInterval(update, 100); this.innerText = '停止'; break; case '停止': clearInterval(work); this.innerText = '开始'; break; } } </script> </html>
模拟广告:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模拟广告</title> <style> *{ padding: 0; margin: 0; } #poster{ width: 100%; height: 100px; background-color: green; color: yellow; font-size: 30px; line-height: 100px; text-align: center; position: fixed; top: 0; } #close_poster{ float: right; } #main{ height: 6000px; width: 1266px; background-color: lightcoral; text-align: center; line-height: 2000px; margin: 0 auto; } </style> </head> <body> <div id="poster"> 我是一个广告,气死你,啊哈哈! <button id="close_poster">X</button> </div> <div id="main">这里是正文</div> </body> <script> var btn = document.getElementById('close_poster'); btn.onclick = function(){ this.parentNode.style.display = 'none'; } </script> </html>
鼠标悬停替换图片,离开时换回来:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>替换图片</title> <style> img{ width: 400px; height: 400px; } </style> </head> <body> <div id="box"> <img src="0.jpg" alt="" id="img"> </div> </body> <script> // 要养成在页面加载完成后再运行JS代码的习惯 window.onload = function () { var img = document.getElementById('img'); img.onmouseover = function () { this.setAttribute('src', 'timg.jpg') }; img.onmouseout = function () { this.setAttribute('src', '0.jpg') } } </script> </html>
模态框:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模态框</title> <style> *{ padding: 0; margin: 0; } #box{ width: 100%; height: 100%; background-color: #b0b0b0; position: absolute; top: 0; } #text{ background-color: white; width: 300px; height: 300px; position: absolute; top: 50%; margin-top: -150px; left: 50%; margin-left: -150px; color: red; line-height: 300px; text-align: center; } #close{ background-color: red; float: right; } </style> </head> <body> <button id="btn">弹出模态框</button> </body> <script> var box = document.createElement('div'); var son = document.createElement('div'); var close = document.createElement('button'); box.id = 'box'; close.id = 'close'; son.id = 'text'; son.innerHTML = '不关我就不让你点网页!'; close.innerHTML = '关闭'; son.appendChild(close); box.appendChild(son); var btn = document.getElementById('btn'); btn.onclick = function () { this.parentNode.appendChild(box); }; close.onclick = function () { box.parentNode.removeChild(box); } </script> </html>
select框的联动效果:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>select框的联动效果</title> </head> <body> <select name="province" id="province"> <option value="0" selected>请选择省份</option> </select> <select name="city" id="city"> <option value="0">请选择城市</option> </select> </body> <script> data = {"河北": ["廊坊", "邯郸"], "北京": ["朝阳区", "海淀区"], "山东": ["威海市", "烟台市"]} var province = document.getElementById('province'); for(i in data){ var p = document.createElement('option'); p.innerHTML = i; province.appendChild(p); } province.onchange = function () { var city = document.getElementById('city'); city.innerText = null; var choice = document.createElement('option'); choice.innerText = '请选择城市'; city.appendChild(choice); var num = this.options.selectedIndex; var city_name = this.children[num].innerText; for(i in data[city_name]){ var c = document.createElement('option'); c.innerHTML = data[city_name][i]; city.appendChild(c) } } </script> </html>
简易留言板:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>简易留言板</title> <style> *{ padding: 0; margin: 0; } .close{ display: inline-block; width: 20px; height: 100%; line-height: 20px; text-align: center; background-color: wheat; cursor: pointer; } </style> </head> <body> <h1>这是一个简易的留言板</h1> <div id="box"></div> <textarea name="text" id="text" cols="30" rows="10"></textarea> <input type="button" id="btn" value="留言"/> <button id="sum">统计</button> </body> <script> var ul = document.createElement('ul'); var box = document.getElementById('box'); box.appendChild(ul); var btn = document.getElementById('btn'); var msg = document.getElementById('text'); var count = 0; btn.onclick = function () { var li = document.createElement('li'); li.innerHTML = msg.value + '<span class="close">X</span>'; var close = li.lastChild; close.onclick = function () { ul.removeChild(this.parentNode); count--; }; var lis = document.getElementsByTagName('li'); if(lis.length==0){ ul.appendChild(li); count++ }else{ ul.insertBefore(li, lis[0]); count++; } msg.value = ''; }; var sum = document.getElementById('sum'); sum.onclick = function () { alert('当前留言条数为:'+count) } </script> </html>
使用js模拟选择器中hover代码示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模拟hover</title> </head> <style> button{ width: 100px; height: 50px; cursor: pointer; } </style> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> </body> <script> var btns = document.getElementsByTagName('button'); for(var i = 0;i < btns.length;i++){ btns[i].onmouseover = function () { this.style.backgroundColor = 'red'; }; btns[i].onmouseout = function () { this.style.backgroundColor = null; } } </script> </html>
tab栏选项卡:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tab选项卡</title> </head> <style> *{ padding: 0; margin: 0; } .foo{ width: 600px; position: relative; margin: 0 auto; } .son{ display: inline-block; width: 200px; height: 100px; line-height: 100px; text-align: center; background-color: #b0b0b0; cursor: pointer; } .text{ background-color: red; height: 400px; width: 600px; line-height: 400px; text-align: center; font-size: 40px; position: absolute; top: 100px; display: none; } .red{ background-color:red; } .xianshi{ display: block; } </style> <body> <div class="foo"> <div class="son" id="1">首页</div><div class="son" id="2">新闻</div><div class="son" id="3">图片</div> <div class="text" id="main">这里是主页的内容</div> <div class="text" id="new">这里是新闻的内容</div> <div class="text" id="jpg">这里是图片的内容</div> </div> </body> <script> var sons = document.getElementsByClassName('son'); var texts = document.getElementsByClassName('text'); for(var i = 0;i < sons.length;i++){ sons[i].onmouseover = function () { this.classList.add('red'); texts[this.id - 1].classList.add('xianshi'); }; sons[i].onmouseout = function () { this.classList.remove('red'); texts[this.id - 1].classList.remove('xianshi'); } } </script> </html>
购物车案例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>购物车</title> </head> <style> *{ padding: 0; margin: 0; } .foo{ position: relative; width: 200px; margin: 0 auto; } .shop{ width: 200px; height: 100px; line-height: 100px; text-align: center; font-size: 30px; background-color: lightgray; } .son{ width: 500px; height: 300px; line-height: 300px; text-align: center; position: absolute; top: 100px; right: 0; background-color: lightsalmon; display: none; } .on_shop{ background-color: lightsalmon; } .show{ display: block; } </style> <body> <div class="foo"> <div class="shop"> 我的购物车 </div> <div class="son"> 这里是我的购物清单 </div> </div> </body> <script> var shop = document.getElementsByClassName('shop')[0]; var son = document.getElementsByClassName('son')[0]; shop.onmouseover = function () { shop.classList.add('on_shop'); son.classList.add('show'); }; shop.onmouseout = function () { shop.classList.remove('on_shop'); son.classList.remove('show'); } </script> </html>
计时器:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>计时器</title> <style> span{ font-size: 30px; } .num{ display: inline-block; width: 50px; height: 100px; line-height: 100px; text-align: center; font-size: 30px; background-color: lightcyan; border-radius: 10px; } button{ width: 120px; margin-top: 20px; } </style> </head> <body> <div> <div class="num" id="hour1">0</div> <div class="num" id="hour0">0</div> <span>:</span> <div class="num" id="minute1">0</div> <div class="num" id="minute0">0</div> <span>:</span> <div class="num" id="second1">0</div> <div class="num" id="second0">0</div> </div> <button id="start">开始计时</button> <button id="stop">暂停计时</button> <button id="cancel">重置计时</button> </body> <script> var start = document.getElementById('start'); var stop = document.getElementById('stop'); var cancel = document.getElementById('cancel'); var start_static = true; start.onclick = function () { if (start_static){ start_static = false; timer = setInterval('update("second",6)', 1000); } }; function update(hms, max) { var hms0 = document.getElementById(hms+0); var int0 = parseInt(hms0.innerText); int0++; if(int0 == 10){ int0 = 0; var hms1 = document.getElementById(hms+1); var int1 = parseInt(hms1.innerText); int1++; if(int1 == max){ int1 = 0; if(hms == 'second'){ update('minute', 6); }else if (hms == 'minute'){ update('hour', 10); } } hms1.innerText = int1; } hms0.innerText = int0; } stop.onclick = function () { clearInterval(timer); start_static = true; }; cancel.onclick = function () { clearInterval(timer); var nums = document.getElementsByClassName('num'); for(var i = 0;i < nums.length;i++){ nums[i].innerText = 0; start_static = true; } } </script> </html>
字体随机变色:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>字体随机变色</title> <style> span{ font-size: 40px; } </style> </head> <body> <span>看我七十二变!!!</span> </body> <script> var main = document.getElementsByTagName('span')[0]; setInterval(show, 200); function show() { main.style.color = '#' + parseInt(Math.ceil(Math.random()*16777216 + 0.5),16); } </script> </html>