DOM 基础详解 骑猪看日落 2023-09-27 10:19 96阅读 0赞 #### 文章目录 #### * * 一、Web APIs 简介 * 二、什么是 DOM * 三、获取元素 * 四、事件基础 * * 1.事件三要素 * 2.执行事件过程 * 3.常见的鼠标事件 * 五、操作元素 * * 1.改变元素内容 * 2.修改元素属性 * * 2.1 按钮切换图片 * 2.2 分时显示图片 * 3.修改表单属性 * * 3.1 显示隐藏密码 * 4.修改样式属性 * * 4.1 行内样式操作 * * 4.1.1 关闭二维码 * 4.1.2 循环精灵图 * 4.1.3 隐藏文本框内容 * 4.1.4 排他思想(算法) * 4.2 类名样式操作 * * 4.2.1 密码框验证信息 * 4.2.2 表格隔行变色 * 4.2.3 表单全选取消 * 5.修改自定义属性 * * 5.1 tab 栏切换 * 5.2 H5 自定义属性 * 六、节点操作 * * 1.为什么学习节点 * 2.节点层级 * * 2.1 下拉菜单 * 3.添加节点 * 4.删除节点 * * 4.1 发布及删除留言 * 5.复制节点 ### 一、Web APIs 简介 ### 我们前面已经学习完了 JS 的基本语法,但是发现很多常用的网页交互效果依然无法实现,这时候就需要学习 Web APIs 来帮助我们实现网页的交互功能。 API 是为我们程序员提供的一个接口,帮助我们实现某种功能。Web APIs 是浏览器提供的一套操作浏览器功能和页面元素的 API(BOM 和 DOM)。 ### 二、什么是 DOM ### DOM 是文档对象模型,是 W3C 组织推荐的处理可扩展标记语言(HTML 或 XML)的标准编程接口。W3C 已经定义了一系列的DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。 ![在这里插入图片描述][b86bb5ecd22947bf83aa854b22b25bfa.png_pic_center] > ① 文档:一个页面就是一个文档,DOM 中使用 document 表示; > ② 元素:页面中的所有标签,DOM 中使用 element 表示; > ③ 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示。 `DOM 把以上内容都看做是对象!` ### 三、获取元素 ### DOM 在我们实际开发中主要用来操作元素。获取页面中的元素我们可以使用以下几种方式: **① 根据 ID 获取** 使用 getElementById() 方法可以获取带有 ID 的元素对象。 <div id = "age"> 19 </div> <script> var ager = document.getElementById('age'); console.log(ager); //<div id = "age"> 19 </div> 完整标签选取出来 console.log(typeof ager); //object </script> > 注意点: > ① 因为我们文档页面是从上往下加载的,所以先得有标签,script 写到标签下面; > ② get 获得,element 元素,by 通过(驼峰命名法); > ③ 参数 id 是严格区分大小写的字符串,必须加引号; > ④ 返回的结果是一个元素对象; > ⑤ console.dir 打印我们返回的元素对象,更好地查看里面的属性和方法。 **② 根据标签名获取** 使用 getElementsByTagName() 方法可以返回带有指定标签名的对象集合。 <ul> <li>111</li> <li>222</li> <li>333</li> <li>444</li> </ul> <script> var lis = document.getElementsByTagName('li'); console.log(lis); //[li,li,li,li] console.log(lis[0]); //<li>111</li> for (var i = 0; i < lis.length; i++) { console.log(lis[i]); } //循环打印 </script> > 注意点: > ① 返回的是获取过来的元素对象的集合,是以伪数组的形式存储的; > ② 如果想要依次打印里面的元素对象,我们可以采取遍历的方法实现; > ③ 得到的元素对象是动态的,标签内容改变获取的结果也跟着改变; > ④ 如果页面中只有一个 li,返回的还是伪数组,如果页面中没有该元素,返回的是一个空的伪数组。 当页面中有多个相同的标签时,我们想要有选择地获取某个标签(父元素)内部所有指定标签名的子元素,这个时候可以这样写:element.getElementsByTagName(‘标签名’); <ol id = "ols"> <li>11</li> <li>22</li> <li>33</li> </ol> <script> var ool = document.getElementById('ols'); //通过id值把ols这一个元素获取过来 var lis = ool.getElementsByTagName('li'); //获取指定父元素内的指定子元素 console.log(lis); </script> `注意父元素必须是单个确切的对象,获取时不包括父元素自己!` **③ HTML5 新增方法获取** document.getElementsByClassName('类名'); //根据类名返回元素对象集合 document.querySelector('选择器'); //根据指定选择器返回第一个元素对象 document.querySelectorAll('选择器'); //返回指定选择器内所有元素对象的集合 > ① 任何选择器都可以,切记里面的选择器要加符号(.box、\#box、box); > ② 第一种方法里的类名直接写,不需要加符号。 **④ 获取 body 和 html 元素** document.body; //获取body元素 document.documentElement; //获取html元素 `因为一个页面只有一个 body 和 html,所以直接写就可以了!` ### 四、事件基础 ### JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。 简单理解:触发响应机制。 #### 1.事件三要素 #### 事件有三部分组成,事件源、事件类型和事件处理程序。 > ① 事件源,事件被触发的对象(触发谁?比如一个按钮); > ② 事件类型,如何触发(什么事件?比如鼠标点击、鼠标经过,还是键盘按下); > ③ 事件处理程序,通过一个函数赋值的方式完成。 <!--案例 点击按钮弹出一个对话框--> <button id = "btn">提交</button> <script> var btn = document.getElementById('btn'); btn.onclick = function() { alert('提交成功!'); } </script> #### 2.执行事件过程 #### > ① 获取事件源; > ② 注册事件(绑定事件); > ③ 添加事件处理程序(采取函数赋值形式)。 <!--案例 点击div,控制台输出我被选中了--> <div>123</div> <script> var dic = document.querySelector('div'); //获取事件源 div.onclick = function() { console.log('我被选中了'); } //注册事件并添加事件处理程序 </script> #### 3.常见的鼠标事件 #### ![在这里插入图片描述][2efa73671ae1437b9b2a29a9084762fd.png_pic_center] ### 五、操作元素 ### JavaScript 的 DOM 操作可以改变网页的内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内容、属性等。 #### 1.改变元素内容 #### element.innerText; //从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉 element.innerHTML; //起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行 下面看一个案例! <!--案例 点击按钮,div里面的文字会发生变化--> <button>显示当前系统时间</button> <div>某个时间</div> <script> //获取事件 var btn = document.querySelector('button'); var div = document.querySelector('div'); //也可以不添加事件,获取过来直接操作(打开页面就显示时间 div.innerText = getDate();) btn.onclick = function() { div.innerText = getDate(); } //获取当前时间日期 function getDate() { var date = new Date(); var year = date.getFullYear(); var month = date.date.getMonth() + 1; var dates = date.getDate(); var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; var day = date.getDay(); return '今天是:' + year + '年' + month + '月' + dates + '日' + arr[day]; } </script> > innerText 和 innerHTML 的区别: > ① innerText 不识别 HTML 标签,当修改后的内容有 HTML 标签时,innerText 会直接把标签也显示出来,同时去除空格和换行; > ② innerHTML 是我们 W3C 推荐的标准方法,可识别 HTML标签,同时保留空格和换行(常用); > ③ 这两个属性可修改元素里的内容,同样也可以读取元素内容( console.log(div.innerText); ); #### 2.修改元素属性 #### ##### 2.1 按钮切换图片 ##### <!--案例 点击不同的按钮,切换不同的图片--> <button id = "pg">苹果</button> <button id = "xj">香蕉</button> <img src = "pg.jpg" title = "苹果" alt = ""/> <script> //1.获取元素 var pg = document.getElementById('pg'); var xj = document.getElementById('xj'); var img = document.querySelector('img'); //2.注册事件 处理程序 pg.onclick = function() { img.src = 'pg.jpg'; img.title = '苹果'; } xj.onclick = function() { img.src = 'xj.jpg'; img.title = '香蕉'; } </script> ##### 2.2 分时显示图片 ##### 案例分析: ① 根据系统不同时间判断,所以需要用到日期内置对象; ②利用多分支语句来设置不同的图片; ③ 需要一个图片,并且根据时间修改图片,就需要用到操作元素 src 属性; ④ 需要一个 div 元素,显示不同的问候语,然后修改元素内容即可。 <!--案例 根据不同时间显示不同图片,同时显示不同的问候语--> <img src = "swh.jpg" alt = ""/> <div>上午好</div> <script> //1.获取元素 var img = document.querySelector('img'); var div = document.querySelector('div'); //2.获取当前小时数 var date = new Date(); var h = date.getHours(); //3.判断小时数改变图片和文字信息 if (h < 12) { img.src = 'swh.jpg'; div.innerHTML = '上午好!'; } else if (h >= 12 && h < 18) { img.src = 'xwh.jpg'; div.innerHTML = '下午好!'; } else { img.src = 'wsh.jpg'; div.innerHTML = '晚上好!'; } </script> #### 3.修改表单属性 #### <button>按钮</button> <input type = "text" value = "输入内容"/> <script> var btn = document.querySelector('button'); var input = document.querySelector('input'); btn.onclick = function() { input.value = '被点击了'; //修改表单文本域中的内容 this.disabled = true; //点击之后按钮被禁用,this指向函数的调用者 } </script> > ① innerHTML 这个是修改普通盒子(如 div)里面的内容,而对于表单元素属性的修改我们一律使用属性名; > ② 如果想要一个按钮点击之后被禁用不允许再点击,可以用 disabled 来实现( btn.disabled = true ),实际上我们通常用 this 代替 btn 更简单。 ##### 3.1 显示隐藏密码 ##### 案例分析: ① 核心思路,点击眼睛按钮,把密码框类型改为文本框就可以看见里面的密码了。 ② 一个按钮两种状态,点击一次,切换为文本框,继续点击一次切换为密码框。 ③ 算法,利用一个 flag 变量,通过判断 flag 的值,如果是1就切换为文本框,如果为0就变为密码框。 <!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>显示密码测试</title> <style> body { background-color: cadetblue; } .box { position: relative; width: 240px; border-bottom: 1px solid #ccc; margin: 200px auto; background-color: white; } .box input { width: 210px; height: 26px; border: 0; font-size: 19px; /* 去掉轮廓边框 */ outline: none; } /*通过伪类选择器修改密码框默认提示字体*/ ::-webkit-input-placeholder { color:#ccc; font-size: 16px; } .box img { position: absolute; top: 6px; right: 4px; width: 25px; } </style> </head> <body> <div class="box"> <label for=""> <img src="close.png" id = "eye"/> </label> <input type="password" placeholder="请输入密码" id="pwd"/> </div> <script> var eye = document.getElementById('eye'); var pwd = document.getElementById('pwd'); //利用flag实现睁眼闭眼效果的切换 var flag = 0; eye.onclick = function() { if (flag == 0) { pwd.type = 'text'; eye.src = 'open.png'; flag = 1; }else { pwd.type = 'password'; eye.src = 'close.png'; flag = 0; } } </script> </body> </html> `特别记住,要学会利用 flag 值来合理切换不同情况下的事件!` 运行结果: ![在这里插入图片描述][2ebfc69471454f60b9862594d5a00bf9.png_pic_center] ![在这里插入图片描述][bdd38b416417453fb05e469cca3b23d6.png] 我把这两个眼睛图片也放这里吧,有需要自行保存! ![在这里插入图片描述][2fe4465fd5c34566b3b9b0bc22c10750.jpeg_pic_center] ![在这里插入图片描述][fa81da2797854de1a66caee7dd12dc07.jpeg_pic_center] #### 4.修改样式属性 #### element.style; //行内样式操作 element.className; //类名样式操作 ##### 4.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> <style> div { width: 200px; height: 200px; background-color: blue; } </style> </head> <body> <div></div> <script> var div = document.querySelector('div'); div.onclick = function() { this.style.backgroundColor = 'pink'; //属性采取驼峰命名法 } </script> </body> </html> > 注意: > ① JS 里的样式属性采取驼峰命名法(比如:fontSize、backgroundColor 等); > ② JS 修改 style 样式操作,产生的是行内样式,权重较高。 ###### 4.1.1 关闭二维码 ###### 案例分析: ① 核心思路:利用样式的显示和隐藏完成,display: none 隐藏元素,display: block 显示元素。 ② 点击叉号,就让这个二维码盒子隐藏起来。 <div class = "box"> 二维码 <img src = "ewm.jpg" alt = ""/> <i class = "close-btn">x</i> </div> <script> var btn = document.querySelector('.close-btn'); var box = document.querySelector('.box'); btn.onclick = function() { box.style.display = 'none'; } </script> `注意不是删掉,而是隐藏起来了!` ###### 4.1.2 循环精灵图 ###### 如果使用我们以往的方法添加精灵图,会使得我们的代码量非常大,写起来也很麻烦。那么有没有一种简单的方法,可以一次性添加大量的精灵图呢?当然是有的,我们可以利用 for 循环设置一组元素的精灵图背景。(这里不知道精灵图是什么的,可以看我上一篇文章。) 案例分析: ① 首先精灵图图片的排列是有规律的; ② 核心思路,利用 for 循环修改精灵图片的背景位置(background-position); ③ 让循环里面的 i 索引号 \* 44 就是每个图片的 y 坐标(竖着排列两个精灵图的间隔测量出来是44)。 <!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>循环精灵图</title> <style> * { margin: 0; padding: 0; } li { list-style-type: none; } .box { width: 250px; margin: 100px auto; } .box li { float: left; width: 24px; height: 24px; background-color: brown; margin: 15px; background: url(图.png) no-repeat; } </style> </head> <body> <div class="box"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </div> <script> var lis = document.querySelectorAll('li'); for (var i = 0; i < lis.length; i++) { var index = i * 44; lis[i].style.backgroundPosition = '0 -' + index + 'px'; } </script> </body> </html> ![在这里插入图片描述][e5c5ab12212146b6aa627b95863036b0.png_pic_center] `前提是精灵图里面的小图标要竖着排列,保证间隔一致!` ###### 4.1.3 隐藏文本框内容 ###### 当鼠标点击文本框时,里面的默认文字隐藏,当鼠标离开文本框时,里面的文字显示。 案例分析: ① 首先表单需要两个新事件,获得焦点 onfocus 失去焦点 onblur; ② 如果获得焦点,判断表单里面内容是否为默认文字,如果是默认文字就清空表单内容; ③ 如果失去焦点,判断表单内容是否为空,如果为空则将表单内容修改为默认文字。 <input type = "text" value = "手机"/> <script> var text = document.querySelector('input'); //获得焦点事件 text.onfocus = function() { if (this.value === '手机') { this.value = ''; } //获得焦点时需要把文本框里面的文字颜色变黑 this.style.color = '#333'; } //失去焦点 text.onblur = function() { if (this.value === '') { this.value = '手机'; } //失去焦点时需要把文本框里面的文字颜色变浅 this.style.color = '#999'; } </script> ###### 4.1.4 排他思想(算法) ###### 案例分析: ① 这里有一组按钮,当我们点击一个按钮的时候,只有该按钮变色,且其它按钮都恢复原色; ② 需要用到循环的排他算法。 ③ 所有元素全部清除样式,只给当前元素设置样式。 ④ 注意顺序不能颠倒,首先清除他人,然后设置自己。 <!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>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> var btns = document.getElementsByTagName('button'); for (var i = 0; i < btns.length; i++) { btns[i].onclick = function() { //1.清空所有按钮的样式 for (var i = 0; i < btns.length; i++) { btns[i].style.backgroundColor = ''; } //2.再给自己设置样式 this.style.backgroundColor = 'blue'; } } </script> </body> </html> ##### 4.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> <style> .box { width: 400px; height: 600px; background-color: blue; font-size: 30px; color: black; margin: 200px 200px; } .change { width: 400px; height: 400px; background-color: coral; margin: auto; } </style> </head> <body> <div class = "box">大盒子<div> <script> var box = document.querySelector('div'); box.onclick = function() { if (this.className === 'change') { this.className = 'box'; }else { this.className = 'change'; } } </script> </body> </html> > 注意: > ① 如果样式修改较多,可以采用操作类名方式更改元素样式; > ② class 是个保留字,因此使用 className 来操作元素类名属性; > ③ className 会直接更改元素的类名,也就是会直接覆盖掉原先的类名。 但是大多数时候,我们并不需要把原先类里面所有的属性都修改掉,大量重复的样式再写进新的类里面显然是很繁琐的,当然是有办法可以解决的,还记得多类名选择器吗? this.className = 'first change'; 使用多类名选择器,这样我们的新类里面就不需要写那么多本不需变动的样式,只需要将需要改变的样式属性写到新类里面,两个类同时使用即可。 ###### 4.2.1 密码框验证信息 ###### 案例分析: ① 首先判断的事件是表单失去焦点 onblur。 ② 如果输入正确,则提示正确的信息,颜色为绿色,小图标变化。 ③ 如果输入位数不是6到16位,则提示错误信息颜色为红色,小图标变化。 ④ 因为里面变化样式较多,我们采取 className 修改样式。 <!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>密码框验证</title> <style> div { width: 600px; margin: 300px auto; } .message { display: inline-block; font-size: 13px; color: #999; background: url(提示.png) no-repeat left center; background-size:16px 16px; padding-left: 20px; } .wrong { color: red; background-image: url(叉号.png); } .right { color: green; background-image: url(对号.png); } </style> </head> <body> <div> <input type="text" class="ipt"/> <p class="message">请输入6到16位密码!</p> </div> <script> var ipt = document.querySelector('.ipt'); var message = document.querySelector('.message'); ipt.onblur = function() { if (this.value.length < 6 || this.value.length > 16) { message.className = 'message wrong'; message.innerHTML = '您输入的密码位数不满足条件!'; }else { message.className = 'message right'; message.innerHTML = '密码格式正确!'; } } </script> </body> </html> 运行结果:![在这里插入图片描述][333d897ce67044e19f0a1ec2446b0905.png_pic_center] ![在这里插入图片描述][2de2a475bb684036aeff5b1aa7c43608.png_pic_center] ###### 4.2.2 表格隔行变色 ###### 案例分析: ① 用到新的鼠标事件,鼠标经过 onmouseover,鼠标离开 onmouseout。 ② 核心思路,鼠标经过 tr 行,当前行改变背景颜色,鼠标离开后去掉该背景颜色。 ③ 注意第一行 thead 不需要变换颜色,我们要获取的是 tbody 里面的行。 <!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> <style> table { width: 800px; margin: 100px auto; text-align: center; /* 合并相邻边 */ border-collapse: collapse; font-size: 14px; border: 1px solid aqua; } thead tr { height: 30px; background-color: aqua; } tbody tr { height: 30px; } .bg { background-color: burlywood; } </style> </head> <body> <table> <thead> <tr> <th>代码</th> <th>名称</th> <th>累计净值</th> <th>前单位净值</th> <th>净值增长率</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </tbody> </table> <script> var trs = document.querySelector('tbody').querySelectorAll('tr'); for (var i = 0; i < trs.length;i++) { trs[i].onmouseover = function() { this.className = 'bg'; } trs[i].onmouseout = function() { this.className = ''; } } </script> </body> </html> ###### 4.2.3 表单全选取消 ###### 案例分析: ① 全选和取消全选做法:让下面所有复选框的 选中状态(checked 属性)跟随全选按钮的选中状态即可。 ② 下面复选框只要有一个未选中,全选就取消做法:给下面所有复选框绑定点击事件,每次点击都要循环查看其他的复选框有没有全部都选中,如果发现有一个未选中,上面全选取消。 ③ 可以设置一个变量,来控制全选是否选中。 <!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> <style> table { width: 800px; margin: 100px auto; text-align: center; border-collapse: collapse; } thead tr { height: 30px; background-color:rgb(62, 62, 227); } tbody tr { height: 30px; background-color: antiquewhite; } </style> </head> <body> <div class="wrap"> <table> <thead> <tr> <th> <input type="checkbox" id="j_cbAll"/> </th> <th>商品</th> <th>价格</th> </tr> </thead> <tbody id="j_tb"> <tr> <td> <input type="checkbox"/> </td> <td>iPhone8</td> <td>8000</td> </tr> <tr> <td> <input type="checkbox"/> </td> <td>iPad Pro</td> <td>5000</td> </tr> <tr> <td> <input type="checkbox"/> </td> <td>iPad Air</td> <td>2000</td> </tr> <tr> <td> <input type="checkbox"/> </td> <td>Apple Watch</td> <td>2000</td> </tr> </tbody> </table> </div> <script> var j_cbAll = document.getElementById('j_cbAll'); var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); //1.点击全选,下面所有复选框都被选中 j_cbAll.onclick = function() { for (var i = 0; i < j_tbs.length; i++) { j_tbs[i].checked = this.checked; } } //2.复选框只要有一个没有被选中,全选就取消 for (var i = 0; i < j_tbs.length; i++) { j_tbs[i].onclick = function() { //flag控制全选按钮是否被选中 var flag = true; for (var i = 0; i < j_tbs.length; i++) { if (!j_tbs[i].checked) { flag = false; //只要发现有一个没被选中结果就已经确定了,后面无需再判断 break; } } j_cbAll.checked = flag; } } </script> </body> </html> 运行结果: ![在这里插入图片描述][ce4b9031e94f4f5ea97699f040713384.png_pic_center] #### 5.修改自定义属性 #### 对属性的操作我们有两种方法,第一种是我们前面所学的`元素.id`,但是这种方法只能对内置属性进行操作,而我们这里所讲的是另一种方法`元素.setAttribute()`,它不仅能对内置属性进行操作,更主要的功能是用来操作自定义的属性。 <div id-"demo" index = "1"></div> <script> var div = document.querySelector('div'); //获取元素的属性值 var a = div.id; //demo 第一种方法,只能获取内置属性的值 var b = div.getAttribute('id'); //demo 第二种方法,主要用来获取自定义属性的值 //修改元素的属性值 div.setAttribute('id', 'play'); //移除自定义属性 div.removeAttribute('index'); </script> ##### 5.1 tab 栏切换 ##### `重点案例!!` 案例分析: ① 当鼠标点击上面相应的选项卡,下面的内容会跟着变化。 ② Tab 栏有两大模块,点击上面的某一个选项卡,当前这一底色变为红色,其余不变,你是否想到了用排他思想修改类名? ③ 下面的模块内容,会随着上面的选项卡的变化而变化,所以该变化要写到点击事件里面。 ④ 下面的模块显示内容和上面的选项卡是一一对应的,相匹配。 ⑤ 核心思路,给上面的 tab\_list 里面的所有的 li 添加自定义属性,属性值从0开始编号。 ⑥ 点击 tab\_list 里面的某个 li,让 tab\_con 里面对应序号的内容显示,其余隐藏即可。 <!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> <style> .tab { width: 660px; height: 350px; margin: 200px auto; } .tab_list li { float: left; height: 39px; line-height: 39px; padding: 0 20px; text-align: center; list-style: none; cursor: pointer; } .tab_list .current { background-color: brown; color: aliceblue; } .tab_con { font-size: 15px; padding: 60px 41px; } .item { display: none; } </style> </head> <body> <div class="tab"> <div class="tab_list"> <ul> <li class="current">商品介绍</li> <li>规格与包装</li> <li>售后保障</li> <li>商品评价(5000)</li> <li>手机社区</li> </ul> </div> <div class="tab_con"> <div class="item" style="display: block;"> 商品介绍模块内容 </div> <div class="item"> 规格与包装模块内容 </div> <div class="item"> 售后保障模块内容 </div> <div class="item"> 商品评价模块内容 </div> <div class="item"> 手机社区模块内容 </div> </div> </div> <script> var tab_list = document.querySelector('.tab_list'); var lis = tab_list.querySelectorAll('li'); var items = document.querySelectorAll('.item'); //for循环绑定点击事件 for (var i = 0; i < lis.length; i++) { //给li设置索引号 lis[i].setAttribute('index', i); lis[i].onclick = function() { //1.清除所有li的样式 for (var i = 0; i < lis.length; i++) { lis[i].className = ''; } //2.给当前li添加样式 this.className = 'current'; var index = this.getAttribute('index'); for (var i = 0; i < lis.length; i++) { items[i].style.display = 'none'; } items[index].style.display = 'block'; } } </script> </body> </html> 运行结果: ![在这里插入图片描述][bbd8127218ac4ce99ac11911acd0ae93.png_pic_center] ##### 5.2 H5 自定义属性 ##### 自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。 自定义属性通过 getAttribute(‘属性’) 获取。但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。H5 给我们新增了自定义属性,H5 规定自定义属性的属性名都以 data- 开头。 比如`<div data-index = "1"></div>`,或者使用 JS 设置`element.setAttribute('data-index', 2)`。 div.getAttribute('data-index'); //这是我们之前获取自定义属性的方法 div.dataset.index; //这是H5新增的获取自定义属性的方法 div.dataset['index']; //同上 `H5 新增方法只有 ie11 以上版本才支持,所以我们一般还是用老方法 getAttribute!` ### 六、节点操作 ### #### 1.为什么学习节点 #### 获取元素通常使用两种方式: ① 利用 DOM 提供的方法获取(我们前面所学的),缺点就是逻辑性不强,非常繁琐; ② 利用节点层级关系获取,通过父子兄弟节点关系获取元素,相较于上一种方法,它的逻辑性更强,操作简单,但是兼容性较差。 > ① 网页中所有的内容都是节点,在 DOM 中节点用 node 来表示; > ② 一般地,节点至少拥有 nodeType、nodeName 和 nodeValue 这三个基本属性; > ③ 元素节点类型为1,属性节点类型为2,文本节点类型为3; `我们实际开发中,节点操作主要操作的是元素节点!` #### 2.节点层级 #### <ul> <li><li> <li><li> <li><li> <li><li> </ul> <div class="box"> <span class="top"></span> </div> <script> //1.父节点 parentNode返回的是它的父亲(离它最近的父结点) var top = document.querySelector('.top'); console.log(top.parentNode); //2.子节点 children返回所有的元素子节点,也是我们实际开发中常用的 var ul = document.querySelector('ul'); console.log(ul.children); //3.第一个和最后一个子节点 firstChild 和 lastChild var ul = document.querySelector('ul'); console.log(ul.firstChild); //#text 注意这里返回的是第一个子节点(包括文本节点和元素节点等) console.log(ul.firstElementChild); //与上面的不同,这个方法返回的直接是第一个元素子节点,但缺点是兼容性差,低版本不支持 console.log(ul.children[0]); //实际开发中的写法,既没有兼容性问题又可以返回第一个子元素 //4.兄弟节点 不常用 var ul = document.querySelector('ul'); console.log(ul.nextSibling); //返回当前元素的下一个兄弟节点,同样也包含文本节点等所有的节点 console.log(ul.previousSibling); //返回当前元素的上一个兄弟节点,同样也包含文本节点等所有的节点 console.log(ul.nextElementSibling); //返回当前元素的下一个兄弟元素节点,有兼容性问题 console.log(ul.previousElementSibling);//返回当前元素的上一个兄弟元素节点 </script> > 子节点除了 parentNode.children 外,其实还有另一种方法 parentNode.childNodes,但我们不推荐! > 因为它返回的是所有的孩子节点,包括元素节点、文本节点等,想要单独把元素节点显示出来得使用 for 循环来实现,显然太过繁琐。所以我们不使用该方法,但上面的 parentNode.children 是要重点掌握的。 ##### 2.1 下拉菜单 ##### ① 导航栏里面的 li 都要有鼠标经过效果,所以需要循环注册鼠标事件。 ② 核心原理,当鼠标经过, li 里面的 ul 显示,鼠标离开 ul 隐藏。 <!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> <style> * { margin: 0; padding: 0; } li { list-style: none; } a { text-decoration: none; color: black; } .nav { margin: 60px 500px; } .nav>li{ position: relative; float: left; height: 41px; width: 114px; text-align: center; background-color: aliceblue; color: black; } .nav>li>a { display:inline-block; width: 100%; height: 100%; line-height: 41px; } .nav>li>a:hover { background-color:rgb(196, 172, 245); } .nav ul { display: none; position: absolute; top: 41px; left: 0; width: 100%; border-left: 1px solid rgb(196, 92, 231); border-right: 1px solid rgb(196, 92, 231); } .nav ul li { border-bottom: 1px solid rgb(196, 92, 231); } .nav ul li a { display: block; line-height: 37px; font-size: 13px; width: 100%; height: 100%; } .nav ul li a:hover { background-color: antiquewhite; } </style> </head> <body> <ul class="nav"> <li> <a href="#">微博</a> <ul> <li> <a href="#">私信</a> </li> <li> <a href="#">评论</a> </li> <li> <a href="#">@我</a> </li> </ul> </li> <li> <a href="#">博客</a> <ul> <li> <a href="#">博客评论</a> </li> <li> <a href="#">未读提醒</a> </li> </ul> </li> <li> <a href="#">邮箱</a> <ul> <li> <a href="#">免费邮箱</a> </li> <li> <a href="#">VIP邮箱</a> </li> <li> <a href="#">企业邮箱</a> </li> </ul> </li> </ul> <script> var nav = document.querySelector('.nav'); var lis = nav.children; //得到4个li for (var i = 0; i < lis.length; i++) { lis[i].onmouseover = function() { this.children[1].style.display = 'block'; } lis[i].onmouseout = function() { this.children[1].style.display = 'none'; } } </script> </body> </html> 运行结果: ![在这里插入图片描述][0220dd67fc874748b7ea598ad4b36eeb.jpeg_pic_center] #### 3.添加节点 #### //1.创建节点 document.createElement('tagName'); //2.添加节点 两种方法 node.appendChild(child); node.insertBefore(child, 指定元素); ① document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以也称为动态创建元素节点。 ② node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。 ③ node.insertBefore() 方法可以将一个节点添加到父节点的指定子节点前面。 // 给ul添加li <ul></ul> <script> var li = document.createElement('li'); //创建节点元素li var ul = document.querySelector('ul'); ul.appendChild(li); //给父级ul添加子级li,末尾追加(常用) ul.insertBefore(li, ul.children[1]); //将li添加到ul的第二个子节点的前面,索引从0开始 </script> #### 4.删除节点 #### node.removeChild(child); 该方法从 DOM 中删除一个子节点,并返回删除的节点。 ##### 4.1 发布及删除留言 ##### 案例分析: ① 点击按钮之后,就动态创建一个 li,添加到 ul 里面。 ② 创建 li 的同时,把文本域里面的值通过 li.innerHTML 赋值给 li。 ③ 留言在前面显示用 insertBefore 。 ④ 当我们把文本域里面的值赋值给 li 的时候,多添加一个删除的链接。 ⑤ 需要把所有的链接获取过来,当我们点击当前的链接的时候,就删除当前链接所在的 li。 ⑥ 点击删除链接的时候,地址会发生改变,为了阻止链接跳转,href 里面写`javascript:;`即可 <textarea name="" id="">123</textarea> <button>发布</button> <ul> </ul> <script> var btn = document.querySelector('button'); var text = document.querySelector('textarea'); var ul = document.querySelector('ul'); btn.onclick = function() { if (text.value == '') { alert('您没有输入内容!'); return false; }else{ //1.创建元素 var li = document.createElement('li'); li.innerHTML = text.value + "<a href='javascript:;'>删除</a>"; //把文本框中的内容给li,显示出来并添加删除键 //2.添加元素 ul.insertBefore(li, ul.children[0]); //3.删除元素 var as = document.querySelector('a'); for (var i = 0; i < as.length; i++) { as[i].onclick = function() { ul.removeChild(this.parentNode); //当前链接的父亲就是我们要删除的元素li } } } } </script> #### 5.复制节点 #### <ul> <li>1</li> <li>2</li> <li>3</li> </ul> <script> var ul = document.querySelector('ul'); var lili = ul.children[0].cloneNode(true); //将第一个li复制上 ul.appendChild(lili); //将复制好的内容追加到原列表后面 </script> node.cloneNode(); node.cloneNode() 方法返回调用该方法节点的一个副本,也称为克隆节点或拷贝节点。如果括号里面的参数为空或者为 false,则是浅拷贝,即只克隆复制节点本身,并不会克隆里面的内容,只有括号里面为 true 时,才会将标签及标签里面的内容全部复制上。 [b86bb5ecd22947bf83aa854b22b25bfa.png_pic_center]: https://img-blog.csdnimg.cn/b86bb5ecd22947bf83aa854b22b25bfa.png#pic_center [2efa73671ae1437b9b2a29a9084762fd.png_pic_center]: https://img-blog.csdnimg.cn/2efa73671ae1437b9b2a29a9084762fd.png#pic_center [2ebfc69471454f60b9862594d5a00bf9.png_pic_center]: https://img-blog.csdnimg.cn/2ebfc69471454f60b9862594d5a00bf9.png#pic_center [bdd38b416417453fb05e469cca3b23d6.png]: https://img-blog.csdnimg.cn/bdd38b416417453fb05e469cca3b23d6.png [2fe4465fd5c34566b3b9b0bc22c10750.jpeg_pic_center]: https://img-blog.csdnimg.cn/2fe4465fd5c34566b3b9b0bc22c10750.jpeg#pic_center [fa81da2797854de1a66caee7dd12dc07.jpeg_pic_center]: https://img-blog.csdnimg.cn/fa81da2797854de1a66caee7dd12dc07.jpeg#pic_center [e5c5ab12212146b6aa627b95863036b0.png_pic_center]: https://img-blog.csdnimg.cn/e5c5ab12212146b6aa627b95863036b0.png#pic_center [333d897ce67044e19f0a1ec2446b0905.png_pic_center]: https://img-blog.csdnimg.cn/333d897ce67044e19f0a1ec2446b0905.png#pic_center [2de2a475bb684036aeff5b1aa7c43608.png_pic_center]: https://img-blog.csdnimg.cn/2de2a475bb684036aeff5b1aa7c43608.png#pic_center [ce4b9031e94f4f5ea97699f040713384.png_pic_center]: https://img-blog.csdnimg.cn/ce4b9031e94f4f5ea97699f040713384.png#pic_center [bbd8127218ac4ce99ac11911acd0ae93.png_pic_center]: https://img-blog.csdnimg.cn/bbd8127218ac4ce99ac11911acd0ae93.png#pic_center [0220dd67fc874748b7ea598ad4b36eeb.jpeg_pic_center]: https://img-blog.csdnimg.cn/0220dd67fc874748b7ea598ad4b36eeb.jpeg#pic_center
相关 Vue--虚拟DOM(virtual DOM)--详解 原文网址:[Vue--虚拟DOM(virtual DOM)--详解\_IT利刃出鞘的博客-CSDN博客][Vue--_DOM_virtual DOM_--_IT_-CSDN] 冷不防/ 2023年10月01日 15:44/ 0 赞/ 26 阅读
相关 DOM基础 DOM查找 -------------------- JavaScript DOM基础 DOM是Document Object Model(文档对象模型)的缩写 Myth丶恋晨/ 2023年07月17日 14:02/ 0 赞/ 19 阅读
相关 dom基础8 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti 素颜马尾好姑娘i/ 2022年05月01日 12:12/ 0 赞/ 177 阅读
相关 dom基础4 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti 约定不等于承诺〃/ 2022年01月20日 14:47/ 0 赞/ 201 阅读
相关 dom基础3 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti 骑猪看日落/ 2022年01月20日 14:27/ 0 赞/ 234 阅读
相关 dom基础2 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti r囧r小猫/ 2022年01月20日 14:25/ 0 赞/ 209 阅读
相关 dom基础1 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti 矫情吗;*/ 2022年01月20日 14:05/ 0 赞/ 199 阅读
相关 dom基础6 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti 梦里梦外;/ 2022年01月19日 02:15/ 0 赞/ 200 阅读
相关 dom基础5 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <ti 傷城~/ 2022年01月19日 01:11/ 0 赞/ 241 阅读
还没有评论,来说两句吧...