1.DOM树
一个页面的结构是一个树形结构,称为DOM树。
DOM树的树形结构形如:
文档:一个页面就是一个文档,使用document表示
元素:页面中所有的标签都称为元素,使用element表示
节点:网页中所有的内容都可以称为节点,使用node表示。
这些概念在JS代码中就对应一个一个的对象。
2.常用DOM API
2.1 获取元素
要想操作页面上的元素,就需要先拿到对应的JS对象,DOM中提供了一组API能够获取到网页的元素,最常用的就是以下两个API。
querySelector
querySelectorAll
两者都是document的属性,通过页面document的属性和方法,来操作页面的内容。
用法:
let obj=document.querySelector("CSS选择器");
代码示例:
当querySelector的参数匹配器,匹配到了多个元素的时候,此时返回的对象,就是匹配结果中的第一个元素。
像上图的情况,如果想要把所有的li都选中,就需要使用querySelectorAll,其返回的是一个数组,包含了所有被选中的元素。
2.2 事件
事件就是浏览器对于用户的操作行为进行的一个统称,例如鼠标在页面上某个位置点击,就会产生一个鼠标点击事件;再例如鼠标滚轮来滚动页面,就会产生一组滚动事件…
JS的主要工作就是在不同的事件中,进行不同的处理。
事件的三个要素:
事件源:哪个HTML元素产生的事件
事件类型:鼠标移动,鼠标点击,键盘事件,窗口大小改变事件等
事件的处理程序:当事件产生之后,执行怎样的代码
下边我们就用代码来展示最为常见的点击事件:
2.3 操作元素内容
操作元素需要先获取到元素,然后再进行修改,对元素进行修改,无非涉及到内容、属性、样式三个方面。
我们首先来看如何操作元素内容;
对元素内容的操作,我们主要通过Element.innerHTML属性设置或获取HTML语法表示的元素的后代。
语法规则:
//读操作 var content=element.innerHTML; //写操作 element.innerHTML=htmlString;
代码练习:实现计数器
<div id="screen">0</div> <button id="plus">+</button> <script> let plusBtn=document.querySelector("#plus"); plusBtn.onclick=function() { // 1.获取到screen里的值 let screen=document.querySelector("#screen"); let val=screen.innerHTML; // 获取到的值默认为string类型,需要转换成number类型 val=parseInt(val); // 2.val++; val+=1; // 3.把新值写回去 screen.innerHTML=val; } </script>
预览效果:
实现以上代码效果还可以利用input标签来完成,input作为一个单标签,并没有innerHTML属性,但是可以通过的value属性来获取到内部的内容,代码如下:
<input type="text" id="screen" value="0"> <button id="plus">+</button> <script> let plusBtn=document.querySelector("#plus"); plusBtn.onclick=function() { // 1.获取到screen里的值 let screen=document.querySelector("#screen"); let val=screen.value; // 获取到的值默认为string类型,需要转换成number类型 val=parseInt(val); // 2.val++; val+=1; // 3.把新值写回去 screen.value=val; } </script>
2.4 操作元素属性
可以通过Element对象的属性来直接进行修改,就能影响到页面显示效果。
代码示例:
<img src="1.jpg" alt="头像1" title="帅哥"> <script> let img=document.querySelector('img'); console.dir(img); // console.log(img.src); // console.log(img.title); // console.log(img.alt); </script>
通过console.dir这个方法,可以打印出一个dom对象的全部属性和值。
预览结果:
代码练习:点击切换图片
<img src="1.jpg" alt="头像1" title="帅哥"> <script> let img=document.querySelector('img'); img.onclick=function() { console.dir(img); if(img.src.indexOf('1.jpg')>=0) { img.src='2.jpg'; }else if(img.src.indexOf('2.jpg')>=0) { img.src='1.jpg'; } } </script>
预览效果:
我们还可以操作表单元素属性:
表单(主要是指input标签)有以下属性:
value:input值
disabled:禁用
checked:复选框会使用
selected:下拉框会使用
type:input的类型(文本、密码、按钮、文件等)
代码练习:全选/取消全选按钮
1.点击全选按钮,则选中所有选项
2.只要某个选项取消,则自动取消全选按钮的勾选状态。
<input type="checkbox" id="all">我全都要 <br> <input type="checkbox" class="girl">美杜莎 <br> <input type="checkbox" class="girl">云韵 <br> <input type="checkbox" class="girl">萧薰儿 <br> <input type="checkbox" class="girl">雅菲 <br> <script> // 1.获取到元素 let all=document.querySelector('#all'); let girls=document.querySelectorAll('.girl'); // 2.给all注册点击事件,选中/取消所有选项 all.onclick=function() { for(let i=0;i<girls.length;i++) { girls[i].checked=all.checked; } } // 3.给girl注册点击事件 for(let i=0;i<girls.length;i++) { girls[i].onclick=function() { // 检测当前是不是所有的girl都被选中了 all.checked=checkGirls(girls); } } // 4.实现checkGirls function checkGirls(girls) { for(let i=0;i<girls.length;i++) { if(!girls[i].checked) { //只要有一个girl没被选中,就认为结果是false return false; } } // 所有girl都被选中,就是全选中 return true; } </script>
效果预览:
2.5 操作元素样式
操作元素样式本质上也是操作元素属性。
可以通过行内样式或者类名样式来完成操作。
行内样式示例:点击放大字体
element.style.[属性名] = [属性值];
<div style="font-size:20px">这是一个文本</div> <script> let div=document.querySelector('div'); div.onclick=function() { // 1.先获取到当前字体大小 console.log(parseInt(div.style.fontSize)); let fontSize=parseInt(div.style.fontSize); fontSize+=5; div.style.fontSize=fontSize+'px'; } </script>
效果预览:
类名样式示例:开启夜间模式
element.className = [CSS 类名];
class是JS的关键字,所以名字叫做className
点击关灯切换到夜间模式(背景变成黑色)
点击开灯恢复至日间模式(背景变成白色)
<style> .light { background-color: #fff; color: black; } .dark { background-color: #000; color: #fff; } </style> <div class="light" style="height:500px">这是一段话</div> <button>关灯</button> <script> let div=document.querySelector('div'); let button=document.querySelector('button'); button.onclick=function() { if(div.className=='light') { div.className='dark'; button.innerHTML='关灯'; }else if(div.className=='dark') { div.className='light'; button.innerHTML='开灯'; } } </script>
效果预览:
2.6 操作节点
2.6.1 新增节点
1.创建新元素节点
此时该新节点并不能在页面中显示出来,需要在页面的父节点上插入该子结点才能将该新节点显示出来。
2.把元素节点插入到dom树中
2.6.2 删除节点
利用页面父节点的removeChild方法删除节点
3.综合案例
3.1 代码案例:猜数字
期待效果:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button id="resetBtn">重新开始一局游戏</button><br> <span>要猜的数字:</span> <input type="text"> <button id="guessBtn">猜</button><br> <span>结果:</span><span id="result"></span><br> <span>已经猜的次数:</span><span id="guessCount">0</span> <script> // 1.先把上面需要用到的元素拿到 let resetBtn=document.querySelector('#resetBtn'); let input=document.querySelector('input'); let guessBtn=document.querySelector('#guessBtn'); let resultSpan=document.querySelector('#result'); let guessCountSpan=document.querySelector('#guessCount'); // 2.生成一个1-100的随机整数 let toGuess=Math.floor(Math.random()*100)+1; // Math.random()生成[0,1)的数字,乘以一百通过floor向下取整,加一得到[1,100]的随机数 console.log(toGuess); // 3.点击实现猜的逻辑 guessBtn.onclick=function() { // 1.读取到input中输入的内容,并转成整数 if(input.value=='') { return; } let curNum=parseInt(input.value); // 2.判定大小关系,并给出提示 if(curNum<toGuess) { resultSpan.innerHTML='低了'; resultSpan.style.color='red'; }else if(curNum>toGuess) { resultSpan.innerHTML='高了'; resultSpan.style.color='red'; }else { resultSpan.innerHTML='猜对了!'; resultSpan.style.color='green'; } // 3.更新猜的次数 let guessCount=parseInt(guessCountSpan.innerHTML); guessCountSpan.innerHTML=guessCount+1; } // 4.实现reset操作的逻辑(开始新游戏) resetBtn.onclick=function() { // 让页面刷新即可 location.reload(); } </script> </body> </html>
效果预览:
3.2 代码案例:表白墙
期待效果:
代码示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <style> * { margin: 0; padding: 0; box-sizing: border-box; background-color: rgb(30,100,200); } .container { width: 100%; } h3 { text-align: center; padding: 30px 0; font-size: 24px; color: rgb(255,140,10); } p { text-align: center; color: rgba(66, 37, 3, 0.637); font-size: 18px; padding: 5px 0; } .row { width: 400px; height: 50px; margin: 0 auto; display: flex; justify-content: center; align-items: center; } .row span{ width: 100px; height: 40px; text-align: center; padding-right: 0px; font-size: 24px; color: rgb(255,140,10); } .row input { width: 300px; height: 40px; border: 2px solid rgb(255, 140,160); border-radius: 5px; outline: 0; text-align: left; padding-left: 0px; margin-left: 0px; text-indent: 0.4em; font-size: 20px; color: rgb(100,160,255); } .row #submit{ width: 200px; height: 40px; border-radius: 10px; font-size: 24px; border: 0px solid rgb(255, 140, 160); background-color: rgb(255, 140, 160); color: aliceblue; line-height: 40px; margin-top: 8px; } .row #submit:active{ background-color: rgb(140,180,240); } </style> <div class="container"> <h3>表白墙</h3> <p>输入后点击提交,会将信息显示在表格中</p> <div class="row"> <span>谁:</span> <input type="text"> </div> <div class="row"> <span>对谁:</span> <input type="text"> </div> <div class="row"> <span>说:</span> <input type="text"> </div> <div class="row"> <button id="submit">提交</button> </div> </div> <script> // 当用户点击submit,就会获取到input中的内容,从而把内容构造成一个div,插入到页面末尾 let submitBtn=document.querySelector('#submit'); submitBtn.onclick=function() { // 1.获取到3个input中的内容 let inputs=document.querySelectorAll('input'); let from=inputs[0].value; let to=inputs[1].value; let msg=inputs[2].value; if(from==''||to==''||msg=='') { // 用户还没有提交完,暂时先不提交数据 return; } // 2.生成一个新的div,内容是input里面的内容,把这个新的div加到页面中 let div=document.createElement('div'); div.innerHTML=from+'对'+to+'说:'+msg; div.className='row'; let container=document.querySelector('.container'); container.appendChild(div); //3.清空之前输入框内的内容 for(let i=0;i<inputs.length;i++) { inputs[i].value=''; } } </script> </body> </html>
效果预览: