1、DOM概念-文档对象模型
// 什么是DOM ? /* Document Object Model 文档对象模型 面向对象: 三个特性 封装 继承 多态 一个对象: 属性和方法 说 万事万物皆对象 在js没对象 new一个 document对象 html标签对象 head body link style title div p ul li form等
------------------------------------------------------
概念
所谓DOM,全称 Docuemnt Object Model 文档对象模型,毫无疑问,此时要操作对象,什么对象?文档对象
在文档中一切皆对象,比如html,body,div,p等等都看做对象,那么我们如何来点击某个盒子让它变色呢?
DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
解析过程
HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性。
DOM树(一切皆是节点)
上图可知,在HTML当中,一切都是节点:(非常重要)
元素节点:HMTL标签。
文本节点:标签中的文字(比如标签之间的空格、换行)
属性节点::标签的属性
整个html文档就是一个文档节点。所有的节点都是Object。
2、DOM可以做什么
找对象(元素节点)
设置元素的属性值
设置元素的样式
动态创建和删除元素
事件的触发响应:事件源、事件、事件的驱动程序
-----------------------------------------
<!-- DOM可以做什么 比如 让div 颜色切换 (1)找对象(元素节点)(获取DOM) (2)设置标签的属性值 (对于标签属性的操作) (3)设置标签的样式 (对于样式属性的操作) (4) 设置标签值的操作 (5)动态的创建元素和删除元素 (对于DOM的建增删改) (6)事件的触发响应: 事件源 、事件、事件的驱动程序(js事件,ECMAScript相关知识点对DOM进行操作) --> <!-- 开灯 1、先要找到开关 (先要找到事件对象 事件源) 2、摁一下(事件) 3、灯亮了 (业务逻辑 事件驱动) -->
3、DOM的结构
获取文档对象:document
获取html:document.documentElement
获取body: document.body
-----------------------------------------
<body> <div id="box" class="box"></div> <div id="box2" class="box"></div> <script type="text/javascript"> // 1获取文档对象 console.log(document); // 2.获取html console.log(document.documentElement); console.dir(document.documentElement); // 3获取body console.log(document.body); // 4.获取body中元素节点对象的三种方式 // 4.1通过ID获取 var oDiv = document.getElementById('box'); console.log(oDiv); // 4.2 通过类名获取 var oDiv1 = document.getElementsByClassName('box')[0]; console.log(oDiv1); // 4.3 通过标签名获取 var oDiv2 = document.getElementsByTagName('div')[1]; console.log(oDiv2); // HTMLCollection(2) [div#box.box, div#box2.box, box: div#box.box, box2: div#box2.box] 获取的伪数组,不能使用数组的方法 </script> </body>
4、获取其它DOM(事件源)的三种方式
var oDiv1 = document.getElementById("box1"); //方式一:通过id获取单个标签 var oDiv2 = document.getElementsByTagName("div")[0]; //方式二:通过 标签名 获得 标签数组,所以有s var oDiv3 = document.getElementsByClassName("box")[0]; //方式三:通过 类名 获得 标签数组,所以有s
--------------------------------------------------------
----------------------------------------------------------------------------
事件的三要素
事件的三要素:事件源、事件、事件驱动程序。
总结如下:
事件源:引发后续事件的html标签。
事件:js已经定义好了(见下图)。
事件驱动程序:对样式和html的操作。也就是DOM。
入口函数 window.onload()--存在的问题
此函数调用,是当页面加载完毕(文档和图片)的时候,触发onload()函数,文档先加载,图片资源后加载 <script type="text/javascript"> window.onload = function () { console.log("alex"); //等页面加载完毕时,打印字符串 } </script> 有一点我们要知道:js的加载是和html同步加载的。因此,如果使用元素在定义元素之前,容易报错。这个时候,onload事件就能派上用场了,
我们可以把使用元素的代码放在onload里,就能保证这段代码是最后执行。 window.onload()方法存在的问题 图片加载完成才调用onload方法,大家想个问题,如果现在用户访问JD商城页面,如果JD商城中的脚本文件在window.onload()方法调用,
如果此时用户网速卡了,然后图片资源加载失败了,此时用户是做不了任何操作的,所以winodw.onload()方法有很大问题。 window.onload()方法 如果脚本中书写两个这样的方法,那么会有事件覆盖现象。
5、样式属性操作
所谓样式属性,就是对之前所讲解的style标签中的属性进行操作,并且通过js控制盒模型的属性(width,height等),控制盒子的显示隐藏(display:none|block),控制盒子的颜色切换(background:red|green)等等
首先,大家明确一点,你是要操作文档对象了,要遵循事件三步走
获取事件源
事件
事件驱动程序
----------------------------------------------------
<div id='box'></div>
<script>
window.onload = function(){
//1.获取事件源(事件对象,在文档中一切的标签都是对象)
var oDiv = docuement.getElementById('box');
//2.事件
oDiv.onclick = function(){
//3.事件驱动程序 ps:记得 所有的style中使用的像margin-left 在js操作时都是用marginLeft属性进行赋值
oDiv.style.backgroundColor = 'yellow';
}
};
</script>
6、值的操作
所谓值的操作,就是对前闭合标签和后闭合标签中间的文本内容的设置和获取。
双闭合标签: innerText或者innerHTML
单闭合标签:除了img标签,就剩input了,使用value进行赋值
----------------------------------------------
<div id='box'></div> <input type='text' value = 'alex' id='user'> <script> window.onload = function(){ //1.获取事件源(事件对象,在文档中一切的标签都是对象) var oDiv = docuement.getElementById('box'); var oInput = docuement.getElementById('user'); //2.事件 oDiv.onclick = function(){ //3.事件驱动程序 oDiv.innerText = 'alex';//仅仅设置文本内容 oDiv.innerHTML = '<h1>alex</h1>';//将标签和文本内容一起解析 }; //2.事件 oInput.onclick = function(){ //3.事件驱动程序 只有有value属性的 才能使用value赋值和设置值 oInput.value = 'wusir'; } }; </script>
7、标签属性操作
所谓标签属性,就是对标签中(字面上看到的)属性的操作。比如像每个标签中id,class,title、img 标签的src属性和alt属性、a标签的href属性、input标签中的name、type属性等等
-----------------------------------------------------------
<script> //window.onload页面加载完毕以后再执行此代码 window.onload = function () { //需求:鼠标放到img上,更换为另一张图片,也就是修改路径(src的值)。 //步骤: //1.获取事件源 //2.绑定事件 //3.书写事件驱动程序 //1.获取事件源 var oImg = document.getElementById("box"); //2.绑定事件(悬停事件:鼠标进入到事件源中立即出发事件) oImg.onmouseover = function () { //3.书写事件驱动程序(修改src) img.src = "image/jd2.png"; // this.src = "image/jd2.png"; } //2.绑定事件(悬停事件:鼠标进入到事件源中立即出发事件) oImg.onmouseout = function () { //3.书写事件驱动程序(修改src) img.src = "image/jd1.png"; } } </script>
节点的操作
都是函数(方法) 创建节点 格式如下: 新的标签(元素节点) = document.createElement("标签名"); 比如,如果我们想创建一个li标签,或者是创建一个不存在的adbc标签,可以这样做: <script type="text/javascript"> var a1 = document.createElement("li"); //创建一个li标签 var a2 = document.createElement("adbc"); //创建一个不存在的标签 console.log(a1); console.log(a2); console.log(typeof a1); console.log(typeof a2); </script> ------------------------------------------------------------- 插入节点 插入节点有两种方式,它们的含义是不同的。 方式1: 父节点.appendChild(新的子节点); 解释:父节点的最后插入一个新的子节点。 方式2: 父节点.insertBefore(新的子节点,作为参考的子节点); 解释: 在参考节点前插入一个新的节点。 如果参考节点为null,那么他将在父节点最后插入一个子节点。 删除节点 格式如下: 父节点.removeChild(子节点); 解释:用父节点删除子节点。必须要指定是删除哪个子节点。 如果我想删除自己这个节点,可以这么做: node1.parentNode.removeChild(node1);
标签属性操作
<!-- <imgs src="" alt=""> <a href=""></a> --> <a href="javascript:void(0);"> <img src="./images/image.png" alt="上一张" id="prev"> </a> <!-- id class title src href等等 --> <script type="text/javascript"> window.onload = function(){ // 1.获取事件源 var oImg = document.getElementById('prev'); // 2.事件 onmouseover oImg.onmouseover = function(){ // console.log(oImg); // 好比是python中self 谁调用的事件 this指的就是谁 // console.log(this); // ./images/image.png 相对路径 console.log(this.getAttribute('src')); console.log(this.getAttribute('id')); console.log(this.getAttribute('alt')); // 获取的绝对路径 console.log(this.src); console.log(this.id); console.log(this.alt); // 属性的设置 // this.setAttribute('src', './images/image-hover.png'); this.src = './images/image-hover.png'; }; oImg.onmouseout = function(){ this.setAttribute('src', './images/image.png'); } } </script>
效果图:接触和接触显示不同的效果
元素隐藏的几种情况
<style type="text/css"> #box{ 100px; height: 200px; background-color: red; } .active{ display: none; } </style> </head> <body> <button id="btn">隐藏</button> <div id="box" class="box"></div> <script type="text/javascript"> window.onload = function(){ function $(id){ return document.getElementById(id); } /* var isShow = true; $('btn').onclick = function(){ if (isShow) { // 通过控制样式属性的display属性来对盒子的显示和隐藏 $('box').style.display = 'none'; isShow = false; this.innerText = '显示'; }else{ $('box').style.display = 'block'; this.innerText = '隐藏'; isShow = true; } } */ // class // 切换 初始化的时候会有渲染开销 网页中频繁的性切换 我们建议大家使用这种方式 var isShow = true; $('btn').onclick = function(){ if (isShow) { // 在js中设置类得通过className $('box').className += ' active'; this.innerText = '显示'; isShow = false; }else{ // 在js中设置类得通过className $('box').className = 'box'; this.innerText = '隐藏'; isShow = true; } } } </script> </body>
DOM相关案例
1.模态框案例
需求: 打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{ padding: 0; margin: 0; } html,body{ height: 100%; } #box{ 100%; height: 100%; background: rgba(0,0,0,.3); } #content{ position: relative; top: 150px; 400px; height: 200px; line-height: 200px; text-align: center; color: red; background-color: #fff; margin: auto; } #span1{ position: absolute; background-color: red; top: 0; right: 0; 30px; height: 30px; line-height: 30px; text-align: center; color: #fff; } </style> </head> <body> <button id="btn">弹出</button> </body> <script type="text/javascript"> //获取dom元素 1.获取事件源 var oBtn = document.getElementById('btn'); //创建弹出模态框的相关DOM对象 var oDiv = document.createElement('div'); var oP = document.createElement('p'); var oSpan = document.createElement('span'); // 设置属性 oDiv.id = 'box'; oP.id = 'content' oP.innerHTML = '模态框成功弹出' oSpan.innerHTML = 'X'; oSpan.id = 'span1' // 追加元素 oDiv.appendChild(oP); oP.appendChild(oSpan); // 点击弹出按钮 弹出模态框 oBtn.onclick = function(){ //动态的添加到body中一个div this.parentNode.insertBefore(oDiv,oBtn) } // 点击X 关闭模态框 oSpan.onclick = function(){ // 移除oDiv元素 oDiv.parentNode.removeChild(oDiv) } </script> </html>
2、使用js模拟选择器中hover
代码解释: 鼠标悬停时,current栏变色,这里用到了排他思想:先把所有按钮的className设置为空,然后把我(this)这个按钮的className设置为current,就可以达到变色的效果。核心代码是: //排他思想:先把所有按钮的className设置为空,然后把我(this)这个按钮的className设置为current //排他思想和for循环连用 for(var j=0;j<btnArr.length;j++){ btnArr[j].className = ""; } this.className = "current";
-------------------------------------------------------------
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> button { margin: 10px; 100px; height: 40px; cursor: pointer; } .current { background-color: red; } </style> </head> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> //需求:鼠标放到哪个button上,改button变成黄色背景(添加类) var btnArr = document.getElementsByTagName("button"); //绑定事件 for(var i=0;i<btnArr.length;i++){ //要为每一个按钮绑定事件,所以用到了for循环 btnArr[i].onmouseover = function () { //【重要】排他思想:先把所有按钮的className设置为空,然后把我(this)这个按钮的className设置为current //排他思想和for循环连用 for(var j=0;j<btnArr.length;j++){ btnArr[j].className = ""; } this.className = "current"; //【重要】核心代码 } } //鼠标离开current时,还原背景色 for(var i=0;i<btnArr.length;i++){ //要为每一个按钮绑定事件,所以用到了for循环 btnArr[i].onmouseout = function () { //鼠标离开任何一个按钮时,就把按钮的背景色还原 this.className = ""; } } </script> </body> </html>
3.tab(标签)栏选项卡
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{ padding: 0; margin: 0; } ul{ list-style: none; } #tab{ 480px; margin: 20px auto; border: 1px solid red; } ul{ 100%; overflow: hidden; } ul li{ float: left; 160px; height: 60px; line-height: 60px; text-align: center; background-color: #cccccc; } ul li a{ text-decoration: none; color:black; } li.active{ background-color: red; } p{ display: none; height: 200px; text-align: center; line-height: 200px; background-color: red; } p.active{ display: block; } </style> </head> <body> <div id="tab"> <ul> <li class="active"> <a href="#">首页</a> </li> <li> <a href="#">新闻</a> </li> <li> <a href="#">图片</a> </li> </ul> <p class="active">首页内容</p> <p>新闻内容</p> <p>图片内容</p> </div> </body> <script type="text/javascript"> window.onload = function(){ // //需求:鼠标放到上面的li上,li本身变色(添加类),对应的p也显示出来(添加类); //思路:1.点亮上面的盒子。 2.利用索引值显示下面的盒子。 var tabli = document.getElementsByTagName('li'); var tabContent = document.getElementsByTagName('p') for(var i = 0; i < tabli.length; i++){ // 绑定索引值(新增一个自定义属性:index属性) tabli[i].index = i; tabli[i].onclick = function(){ // 1.点亮上面的盒子。 2.利用索引值显示下面的盒子。(排他思想) for(var j = 0; j < tabli.length; j++){ tabli[j].className = ''; tabContent[j].className = ''; } this.className = 'active' tabContent[this.index].className = 'active';//【重要代码】 } } } </script> </html>
-------------------------------------------------------------------
-------------------------------------------------------------------------------
client、offset、scroll系列
他们的作用主要与计算盒模型、盒子的偏移量和滚动有关
clientTop 内容区域到边框顶部的距离 ,说白了,就是边框的高度
clientLeft 内容区域到边框左部的距离,说白了就是边框的乱度
clientWidth 内容区域+左右padding 可视宽度
clientHeight 内容区域+ 上下padding 可视高度
---------------------------------------------------------------------------------------------------
<script type="text/javascript">
/*
* clientTop 内容区域到边框顶部的距离 ,说白了,就是边框的高度
* clientLeft 内容区域到边框左部的距离,说白了就是边框的乱度
* clientWidth 内容区域+左右padding 可视宽度
* clientHeight 内容区域+ 上下padding 可视高度
* */
var oBox = document.getElementsByClassName('box')[0];
console.log(oBox.clientTop); //10
console.log(oBox.clientLeft); //10
console.log(oBox.clientWidth); //360
console.log(oBox.clientHeight); //360
</script>
屏幕的可视区域
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> </body> <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> </html>
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=" 300px;height: 300px;background-color: green"> <div id="box" style=" 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占位高 offsetTop: 如果盒子没有设置定位 到body的顶部的距离,如果盒子设置定位,那么是以父辈为基准的top值 offsetLeft: 如果盒子没有设置定位 到body的左部的距离,如果盒子设置定位,那么是以父辈为基准的left值 * */ console.log(box.offsetTop) console.log(box.offsetLeft) console.log(box.offsetWidth) console.log(box.offsetHeight) } </script> </html>
-------------------------------------------------------------
-------------------------------------------------------------------
scroll演示(onscroll)
实施监听滚动事件 触发此方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{padding: 0;margin: 0;} </style> </head> <body style=" 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=" 200px;height: 200px;border: 1px solid red;overflow: auto;padding: 10px;margin: 5px 0px 0px 0px;"> <p>学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界 </p> </div> </body> <script type="text/javascript"> window.onload = function(){ //实施监听滚动事件 window.onscroll = function(){ // console.log(1111) // 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('上'+s.scrollTop) console.log('左'+s.scrollLeft) console.log('宽'+s.scrollWidth) console.log('高'+s.scrollHeight) } } </script> </html>
定时器 (setTimeout()、setInterval())动画效果
以毫秒为单位
定时器
在js中有两种定时器:
一次性定时器:setTimeout()
周期性循环定时器: setInterval()
setTimeout()
只在指定的时间后执行一次
/定时器 异步运行 function hello(){ alert("hello"); } //使用方法名字执行方法 var t1 = window.setTimeout(hello,1000); var t2 = window.setTimeout("hello()",3000);//使用字符串执行方法 window.clearTimeout(t1);//去掉定时器
setInterval()
在指定时间为周期循环执行
/实时刷新 时间单位为毫秒 setInterval('refreshQuery()',8000); /* 刷新查询 */ function refreshQuery(){ console.log('每8秒调一次') }
---------------------------------------------------
两种方法根据不同的场景和业务需求择而取之,
对于这两个方法,需要注意的是如果要求在每隔一个固定的时间间隔后就精确地执行某动作,那么最好使用setInterval,
而如果不想由于连续调用产生互相干扰的问题,尤其是每次函数的调用需要繁重的计算以及很长的处理时间,那么最好使用setTimeout
/* console.log('开始'); // 一次性定时器 2秒之后会执行回调函数 console.log(22222); 如果它先调用了,证明 setTimeout()可以做异步操作 // 未来 如果对于数据的请求 出现数据阻塞的问题,那么可以考虑使用setTimeout()来执行异步操作 setTimeout(function(){ console.log('走到尽头了'); }, 2000); console.log(22222); */
----------------------
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> #box{ 100px; height: 100px; background-color: yellow; } </style> </head> <body> <div id="box">我的盒子</div> <button id="animate">动画吧</button> <button id="clear">清除定时器</button> <script type="text/javascript"> /* console.log('开始'); // 一次性定时器 2秒之后会执行回调函数 console.log(22222); 如果它先调用了,证明 setTimeout()可以做异步操作 // 未来 如果对于数据的请求 出现数据阻塞的问题,那么可以考虑使用setTimeout()来执行异步操作 setTimeout(function(){ console.log('走到尽头了'); }, 2000); console.log(22222); */ var oDiv = document.getElementById('box'); var oAnimate = document.getElementById('animate'); var num = 0; let timer; oAnimate.onclick = function(){ // 用定时器的时候 要先清定时器 再开定时器 页面不会出现问题 clearInterval(timer); timer = setInterval(function(){ // 控制盒子的步伐 num+=3; console.log(num); oDiv.style.marginLeft = num +'px'; },100); }; // clearInterval(handle?: long) // clearTimeout(handle?: long) var oClear = document.getElementById('clear'); oClear.onclick = function(){ clearInterval(timer); } </script> </body> </html>