js之DOM文档对象模型学习笔记

1、什么是DOM?

文档对象模型( Document Object Model ,简称DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。

一个web页面是一个文档。这个文档可以在浏览器窗口或作为HTML源码显示出来。但上述两个情况中都是同一份文档。文档对象模型(DOM)提供了对同一份文档的另一种表现,存储和操作的方式。 DOM是web页面的完全的面向对象表述,它能够使用如 JavaScript等脚本语言进行修改。所有操作和创建web页面的属性,方法和事件都会被组织成对象的形式(例如, document 对象表示文档本身, table 对象实现了特定的 HTMLTableElement DOM 接口来访问HTML 表格等)。

2、获取元素

DOM在实际开发中主要用来操作元素。操作前先得获取元素。

获取元素的方式:

2.1 根据ID获取;

  使用 getElementById() 方法可以获取带有 ID 的元素对象。
  document.getElementById('id');
  使用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。
 

2.2 根据标签名获取;

  使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
  document.getElementsByTagName('标签名');

  注意:因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。如果获取不到元素,则返回为空的伪数组(因为获取不到对象)

  还可以获取某个元素(父元素)内部所有指定标签名的子元素。
  element.getElementsByTagName('标签名');
  注意:父元素必须是单个对象(必须指明是哪一个元素对象)。获取的时候不包括父元素自己。
 

2.3 通过HTML5新增的方法获取

    1. document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
    2. document.querySelector('选择器如#btn'); // 根据指定选择器返回第一个元素对象,.nav,#btn,input
    3. document.querySelectorAll('选择器'); // 根据指定选择器返回所有元素对象,伪数组

2.4 特殊元素获取

    获取body元素:doucumnet.body // 返回body元素对象

    获取html元素:document.documentElement // 返回html元素对象

 

3、事件基础

3.1 事件简介

JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。
简单理解: 触发--- 响应机制。
网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。

 

3.2 事件三要素

1. 事件源 (谁)
2. 事件类型 (什么事件)
3. 事件处理程序 (做啥)

如:点击按钮弹出对话框功能

var btn = document.getElementById('btn');
btn.onclick = function() {
  alert('你好吗');
};

3.3 常见鼠标事件

onclick:鼠标点击左键触发
onmouseover:鼠标经过触发
onmouseout:鼠标离开触发
onmousedown:鼠标按下触发
onfocus:获得鼠标焦点触发;
onblur:失去鼠标焦点触发
 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <button id="btn">关灯</button>
 9     <script>
10         var btn = document.getElementById('btn');
11         var flag = 0;
12         btn.onclick = function() {
13             if (flag === 0) {
14                 document.body.style.backgroundColor = 'black';
15                 this.innerHTML = '开灯';
16                 flag = 1;
17             } else {
18                 document.body.style.backgroundColor = '#fff';
19                 this.innerHTML = '关灯';
20                 flag = 0;
21             }
22         }
23     </script>
24 </body>
25 </html>
开关灯案例
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         input{
 8             color:#333;
 9         }
10     </style>
11 </head>
12 <body>
13     <div>
14         <input type="text" placeholder="手机">
15     </div>
16     <script>
17         var text = document.querySelector('input');
18         text.onfocus = function () {
19             text.placeholder = '';
20         };
21         text.onblur = function () {
22             text.placeholder = '手机';
23         }
24     </script>
25 </body>
26 </html>
显示隐藏文本框案例

 

4、操作元素

JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内
容 、属性等。
 

4.1 元素内容修改

element.innerHTML :
  起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行。
element.innerText :
  从起始位置到终止位置的内容, 但它去除 html 标签, 同时空格和换行也会去掉。
表单元素属性操作:type,value,selected,checked,disabled
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>登录</title>
 6     <style>
 7         .box{
 8             width:300px;
 9             border-bottom:1px solid #CCCCCC;
10             position: relative;
11             margin: 100px auto;
12         }
13         .box input{
14             width: 270px;
15             height: 30px;
16             border:0;
17             outline: none;
18         }
19         .box img{
20             width: 24px;
21             position: absolute;
22             top:2px;
23             right:2px;
24         }
25     </style>
26 </head>
27 <body>
28     <div class="box">
29         <label for="">
30             <img src="images/close.png" alt="">
31         </label>
32         <input type="password">
33     </div>
34     <script>
35         var img = document.querySelector('img');
36         var input = document.querySelector('input');
37         img.onclick = function () {
38             if(input.type === 'password'){
39                 input.type = "text";
40                 img.src = "images/open.png";
41             }else if(input.type === 'text'){
42                 input.type = "password";
43                 img.src = "images/close.png";
44             }
45 
46 
47         }
48     </script>
49 </body>
50 </html>
登录案例

   

4.2 样式属性的获取和修改

  对于内联样式,获取和设置样式只靠style属性就可以,因为element.style属性返回的是类似数组的一组样式属性及对应值,因此访问具体样式的时候可以采取两种方式即“ele.style.属性名称”和“ele.style['属性名称']”。但是,要注意的是,针对css样式里background-color;margin-left之类的短杠相接的属性名称,在使用style属性获取设置样式的时候名称要改为驼峰式,如ele.style.backgroundColor。
 

  但是,实际情况是文档在现在都基本遵循分离思想,样式基本都是外部链接,这时就要使用其他方法进行获取,而在这种情况下进行样式获取时,不同的浏览器又有不同的处理方式(主要是ie和非ie),因此根据浏览器可以分为两种方式:

1、非ie浏览器中,使用document.defaultView对象的getComputedStyle(ele,null/伪类)方法,该方法接受两个参数,第一个为要考察的元素,第二个则要根据情况,如果只是考察元素本身则为null,如果要 考察伪类,则为响应的伪类。该方法获取到的为元素应用的最终样式组合,同样是类似数组的一个实例。

2、在ie浏览器中,对getComputedStyle()方法不支持,但是针对每个标签元素都有一个近似于style属性的currentStyle的属性,且用法和style用法相同。只不过获取到的样式范围不一样。currenStyle获取到的和getComputedStyle()方法相接近。

为了在处理时达到兼容,可以根据这两种不同的处理方式创建一个函数来达到兼容目的,使得不管在那种浏览器中,都可以成功获取样式。如下所示:(判断是否支持currentStyle)

var eleFinalStyle = element.currentStyle ? element.currentStyle : getComputedStyle(element, null); 

注意:通过currentStyle和getComputedStyle()读取到的样式都是只读的,不能修改,如果要修改必须听过style属性:

element.style.width = 200px;

 
 
如果样式修改较多,可以采取操作类名方式更改元素样式:element.className 
class因为是个保留字,因此使用className来操作元素类名属性。
className 会直接更改元素的类名,会覆盖原先的类名。
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         div{
 8             width: 600px;
 9             margin: 100px auto;
10         }
11         .message {
12             display: inline-block;
13             font-size: 12px;
14             color: #999999;
15             background: url(images/mess.png) no-repeat ;
16             padding-left: 20px;
17             margin-left: 10px;
18         }
19         .wrong{
20             color:red;
21             background: url(images/wrong.png) no-repeat ;
22         }
23         .right {
24             color: green;
25             background: url(images/right.png) no-repeat ;
26         }
27     </style>
28 </head>
29 <body>
30     <div class="register">
31         <input type="text" class="ipt">
32         <p class="message">请输入6-16位的密码</p>
33     </div>
34     <script>
35         //输入的密码长度不在6-16位之间失去焦点后展示红色提示信息,获得焦点后提示信息显示默认值
36         var div = document.querySelector('div');
37         var input = document.querySelector('.ipt');
38         var message = document.querySelector('.message');
39         input.onblur = function () {
40             if(this.value.length<6 || input.value.length>16){
41                 message.className = 'message wrong';
42                 message.innerHTML = '密码格式不正确';
43             }else{
44                 message.className = 'message right';
45                 message.innerHTML = '密码格式正确';
46             }
47         };
48         input.onfocus = function () {
49             message.className = 'message';
50             message.innerHTML = '请输入6-16位的密码';
51 
52         }
53     </script>
54 </body>
55 </html>
注册错误信息提示案例

   

4.3 排他思想

如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:

1. 所有元素全部清除样式(干掉其他人)

2. 给当前元素设置样式 (留下我自己)

3. 注意顺序不能颠倒,首先干掉其他人,再设置自己

 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         * {
 8             margin: 0;
 9             padding: 0;
10         }
11         .change{
12             overflow: hidden;
13             margin: 100px auto;
14             width: 410px;
15             background-color: #fff;
16             padding-top: 3px;
17         }
18         li{
19             list-style-type: none;
20             float: left;
21             margin: 0 1px;
22         }
23         li img{
24             width: 100px;
25         }
26     </style>
27 </head>
28 <body>
29 <ul class="change">
30     <li><img src="images/1.jpg" alt=""></li>
31     <li><img src="images/2.jpg" alt=""></li>
32     <li><img src="images/3.jpg" alt=""></li>
33     <li><img src="images/4.jpg" alt=""></li>
34 </ul>
35 <script>
36     var imgs = document.querySelector('.change').querySelectorAll('img');
37     for (var i = 0; i < imgs.length; i++) {
38         imgs[i].onclick = function () {
39             document.body.style.background = 'url('+this.src+')';
40         }
41     }
42 </script>
43 
44 </body>
45 </html>
百度换肤案例
  1 <!DOCTYPE html>
  2 <html lang="en">
  3 
  4 <head>
  5     <meta charset="UTF-8">
  6     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7     <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8     <title>Document</title>
  9     <style>
 10         table {
 11             width: 800px;
 12             margin: 100px auto;
 13             text-align: center;
 14             border-collapse: collapse;
 15             font-size: 14px;
 16         }
 17         
 18         thead tr {
 19             height: 30px;
 20             background-color: skyblue;
 21         }
 22         
 23         tbody tr {
 24             height: 30px;
 25         }
 26         
 27         tbody td {
 28             border-bottom: 1px solid #d7d7d7;
 29             font-size: 12px;
 30             color: blue;
 31         }
 32         
 33         .bg {
 34             background-color: pink;
 35         }
 36     </style>
 37 </head>
 38 
 39 <body>
 40     <table>
 41         <thead>
 42             <tr>
 43                 <th>代码</th>
 44                 <th>名称</th>
 45                 <th>最新公布净值</th>
 46                 <th>累计净值</th>
 47                 <th>前单位净值</th>
 48                 <th>净值增长率</th>
 49             </tr>
 50         </thead>
 51         <tbody>
 52             <tr>
 53                 <td>003526</td>
 54                 <td>农银金穗3个月定期开放债券</td>
 55                 <td>1.075</td>
 56                 <td>1.079</td>
 57                 <td>1.074</td>
 58                 <td>+0.047%</td>
 59             </tr>
 60             <tr>
 61                 <td>003526</td>
 62                 <td>农银金穗3个月定期开放债券</td>
 63                 <td>1.075</td>
 64                 <td>1.079</td>
 65                 <td>1.074</td>
 66                 <td>+0.047%</td>
 67             </tr>
 68             <tr>
 69                 <td>003526</td>
 70                 <td>农银金穗3个月定期开放债券</td>
 71                 <td>1.075</td>
 72                 <td>1.079</td>
 73                 <td>1.074</td>
 74                 <td>+0.047%</td>
 75             </tr>
 76             <tr>
 77                 <td>003526</td>
 78                 <td>农银金穗3个月定期开放债券</td>
 79                 <td>1.075</td>
 80                 <td>1.079</td>
 81                 <td>1.074</td>
 82                 <td>+0.047%</td>
 83             </tr>
 84             <tr>
 85                 <td>003526</td>
 86                 <td>农银金穗3个月定期开放债券</td>
 87                 <td>1.075</td>
 88                 <td>1.079</td>
 89                 <td>1.074</td>
 90                 <td>+0.047%</td>
 91             </tr>
 92             <tr>
 93                 <td>003526</td>
 94                 <td>农银金穗3个月定期开放债券</td>
 95                 <td>1.075</td>
 96                 <td>1.079</td>
 97                 <td>1.074</td>
 98                 <td>+0.047%</td>
 99             </tr>
100         </tbody>
101     </table>
102     <script>
103         // 1.获取元素 获取的是 tbody 里面所有的行
104         var trs = document.querySelector('tbody').querySelectorAll('tr');
105         // 2. 利用循环绑定注册事件
106         for (var i = 0; i < trs.length; i++) {
107             // 3. 鼠标经过事件 onmouseover
108             trs[i].onmouseover = function() {
109                     this.className = 'bg';
110                 };
111                 // 4. 鼠标离开事件 onmouseout
112             trs[i].onmouseout = function() {
113                 this.className = '';
114             }
115         }
116     </script>
117 </body>
118 
119 </html>
表格变色案例
  1 <!DOCTYPE html>
  2 <html>
  3 
  4 <head lang="en">
  5     <meta charset="UTF-8">
  6     <title></title>
  7     <style>
  8         * {
  9             padding: 0;
 10             margin: 0;
 11         }
 12 
 13         .wrap {
 14             width: 300px;
 15             margin: 100px auto 0;
 16         }
 17 
 18         table {
 19             border-collapse: collapse;
 20             border-spacing: 0;
 21             border: 1px solid #c0c0c0;
 22             width: 300px;
 23         }
 24 
 25         th,
 26         td {
 27             border: 1px solid #d0d0d0;
 28             color: #404060;
 29             padding: 10px;
 30         }
 31 
 32         th {
 33             background-color: #09c;
 34             font: bold 16px "微软雅黑";
 35             color: #fff;
 36         }
 37 
 38         td {
 39             font: 14px "微软雅黑";
 40         }
 41 
 42         tbody tr {
 43             background-color: #f0f0f0;
 44         }
 45 
 46         tbody tr:hover {
 47             cursor: pointer;
 48             background-color: #fafafa;
 49         }
 50     </style>
 51 
 52 </head>
 53 
 54 <body>
 55     <div class="wrap">
 56         <table>
 57             <thead>
 58                 <tr>
 59                     <th>
 60                         <input type="checkbox" id="j_cbAll" />
 61                     </th>
 62                     <th>商品</th>
 63                     <th>价钱</th>
 64                 </tr>
 65             </thead>
 66             <tbody id="j_tb">
 67                 <tr>
 68                     <td>
 69                         <input type="checkbox" />
 70                     </td>
 71                     <td>iPhone8</td>
 72                     <td>8000</td>
 73                 </tr>
 74                 <tr>
 75                     <td>
 76                         <input type="checkbox" />
 77                     </td>
 78                     <td>iPad Pro</td>
 79                     <td>5000</td>
 80                 </tr>
 81                 <tr>
 82                     <td>
 83                         <input type="checkbox" />
 84                     </td>
 85                     <td>iPad Air</td>
 86                     <td>2000</td>
 87                 </tr>
 88                 <tr>
 89                     <td>
 90                         <input type="checkbox" />
 91                     </td>
 92                     <td>Apple Watch</td>
 93                     <td>2000</td>
 94                 </tr>
 95 
 96             </tbody>
 97         </table>
 98     </div>
 99     <script>
100         // 1. 全选和取消全选做法:  让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
101         // 获取元素
102         var j_cbAll = document.getElementById('j_cbAll'); // 全选按钮
103         var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); // 下面所有的复选框
104         // 注册事件
105         j_cbAll.onclick = function() {
106                 // this.checked 它可以得到当前复选框的选中状态如果是true 就是选中,如果是false 就是未选中
107                 for (var i = 0; i < j_tbs.length; i++) {
108                     j_tbs[i].checked = this.checked;
109                 }
110             };
111             // 2. 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
112         for (var i = 0; i < j_tbs.length; i++) {
113             j_tbs[i].onclick = function() {
114                 // flag 控制全选按钮是否选中
115                 var flag = true;
116                 // 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
117                 for (var i = 0; i < j_tbs.length; i++) {
118                     if (!j_tbs[i].checked) {
119                         flag = false;
120                         break; // 退出for循环 这样可以提高执行效率 因为只要有一个没有选中,剩下的就无需循环判断了
121                     }
122                 }
123                 j_cbAll.checked = flag;
124             }
125         }
126     </script>
127 </body>
128 
129 </html>
表单全选案例

   

4.4 自定义属性操作

获取属性

1 、element.属性名  
  获取内置属性值(元素本身自带的属性)
2、element.getAttribute('属性名');
  主要获得自定义的属性 (标准)

设置属性值

element.属性 = ‘值’ 设置内置属性值。 
element.setAttribute('属性', '值');

移除属性

element.属性=' '
element.removeAttribute('属性');
   

4.5 自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(‘属性’) 获取。
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
H5给我们新增了自定义属性:

设置H5自定义属性

  H5规定自定义属性data-开头做为属性名并且赋值。比如 <div data-index=“1”></div>
  或者使用 JS 设置,element.setAttribute(‘data-index’, 2)

获取H5自定义属性

1. 兼容性获取 element.getAttribute(‘data-index’);
2. H5新增 element.dataset.index 或者 element.dataset[‘index’] ie 11才开始支持
 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <style>
 7         *{
 8             margin: 0;
 9             padding: 0;
10         }
11         .tab{
12             width: 500px;
13             margin: 200px auto;
14         }
15         .tab-list li{
16             float: left;
17             width: 125px;
18             height: 50px;
19             line-height: 50px;
20             text-align: center;
21             cursor: pointer;
22         }
23         .current{
24             background-color: pink;
25         }
26         .tab-content{
27             margin-top: 30px;
28         }
29         li{
30             list-style-type: none;
31         }
32         .item{
33             padding-top: 20px;
34             display:none;
35         }
36     </style>
37 </head>
38 <body>
39 <div class="tab">
40     <div class="tab-list">
41         <ul>
42             <li class="current" >华为</li>
43             <li >小米</li>
44             <li >苹果</li>
45             <li >三星</li>
46         </ul>
47     </div>
48     <div class="tab-content">
49         <div class="item"  style="display: block;">这是华为手机</div>
50         <div class="item" >这是小米手机</div>
51         <div class="item" >这是苹果手机</div>
52         <div class="item" >这是三星手机</div>
53     </div>
54     <script>
55         //要求点击上面的手机类后背景色变粉,下面也显示相对应的手机信息。
56         //变色可用排他循环思想处理;下面映射关系的改变,可以在上下都添加一个自定义属性,
57         //其属性值一一对应,点击后获得上面的属性值,在下面遍历获得各自属性值,若下面属性值有与上面
58         //相等的,就将下面div样式中的display改为block,不等改为none即可。
59 
60         var lists = document.querySelector('.tab-list').querySelectorAll('li');
61         var items = document.querySelectorAll('.item');
62         for (var i = 0; i < lists.length; i++) {
63             lists[i].setAttribute('data-index',i);
64             lists[i].onclick = function () {
65                 for (var i = 0; i < lists.length; i++) {
66                     lists[i].className = '';
67                 }
68                 this.className = 'current';
69                 var index = this.getAttribute('data-index');
70                 for (var j = 0; j < items.length; j++) {
71                     items[j].setAttribute('data-index', j);
72                     if (items[j].getAttribute('data-index') === index) {
73                         items[j].style.display = 'block';
74                     } else {
75                         items[j].style.display = 'none'
76                     }
77                 }
78             }
79         }
80     </script>
81 
82 </div>
83 </body>
84 </html>
Tab栏切换案例

   内地阿飞飞发if你发奶奶

5、节点操作

 
利用DOM提供的方法获取元素逻辑性不强,并且很繁琐,如 document.getElementsByTagName()
利用父子兄节点层级关系获取元素则逻辑性更强,也更简单些。

5.1 节点概述

网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。
HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以创建或删除。
 
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
元素节点 nodeType 为 1
属性节点 nodeType 为 2
文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
在实际开发中,节点操作主要操作的是元素节点。
 

5.2 节点层级

利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。

父级节点

node.parentNode
parentNode 属性可返回某节点的父节点,注意是最近的一个父节点;
如果指定的节点没有父节点则返回 null;
 

子节点

1. parentNode.childNodes(标准)
parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes
var ul = document. querySelector(‘ul’);
for(var i = 0; i < ul.childNodes.length;i++) {
  if (ul.childNodes[i].nodeType == 1) {
    // ul.childNodes[i] 是元素节点
    console.log(ul.childNodes[i]);
  }
}
 
2. parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回 (这个是我们重点掌握的)。
虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用。
3. parentNode.firstChild
firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
4. parentNode.lastChild
lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。
5. parentNode.firstElementChild
firstElementChild 返回第一个子元素节点,找不到则返回null。
6. parentNode.lastElementChild
lastElementChild 返回最后一个子元素节点,找不到则返回null。
注意:这两个方法有兼容性问题,IE9 以上才支持。
 
实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和
lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
解决方案:
1. 如果想要第一个子元素节点,可以使用 parentNode.chilren[0]
2. 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]
  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <title>Title</title>
  6     <style>
  7         * {
  8             margin: 0;
  9             padding: 0;
 10         }
 11 
 12         li {
 13             list-style-type: none;
 14         }
 15 
 16         a {
 17             text-decoration: none;
 18             font-size: 14px;
 19         }
 20 
 21         .nav {
 22             margin: 100px;
 23         }
 24 
 25         .nav>li {
 26             position: relative;
 27             float: left;
 28             width: 80px;
 29             height: 41px;
 30             text-align: center;
 31         }
 32 
 33         .nav li a {
 34             display: block;
 35             width: 100%;
 36             height: 100%;
 37             line-height: 41px;
 38             color: #333;
 39         }
 40 
 41         .nav>li>a:hover {
 42             background-color: #eee;
 43         }
 44 
 45         .nav ul {
 46             display: none;
 47             position: absolute;
 48             top: 41px;
 49             left: 0;
 50             width: 100%;
 51             border-left: 1px solid #FECC5B;
 52             border-right: 1px solid #FECC5B;
 53         }
 54 
 55         .nav ul li {
 56             border-bottom: 1px solid #FECC5B;
 57         }
 58 
 59         .nav ul li a:hover {
 60             background-color: #FFF5DA;
 61         }
 62     </style>
 63 </head>
 64 
 65 <body>
 66     <ul class="nav">
 67         <li>
 68             <a href="#">视频</a>
 69             <ul>
 70                 <li>
 71                     <a href="">电影</a>
 72                 </li>
 73                 <li>
 74                     <a href="">电视剧</a>
 75                 </li>
 76                 <li>
 77                     <a href="">动画片</a>
 78                 </li>
 79             </ul>
 80         </li>
 81         <li>
 82             <a href="#">图片</a>
 83             <ul>
 84                 <li>
 85                     <a href="">风景</a>
 86                 </li>
 87                 <li>
 88                     <a href="">唯美</a>
 89                 </li>
 90                 <li>
 91                     <a href="">人物</a>
 92                 </li>
 93                 <li>
 94                     <a href="">小清新</a>
 95                 </li>
 96             </ul>
 97         </li>
 98         <li>
 99             <a href="#">文章</a>
100             <ul>
101                 <li>
102                     <a href="">散文</a>
103                 </li>
104                 <li>
105                     <a href="">小说</a>
106                 </li>
107                 <li>
108                     <a href="">诗歌</a>
109                 </li>
110             </ul>
111         </li>
112         <li>
113             <a href="#">其他</a>
114             <ul>
115                 <li>
116                     <a href="">联系</a>
117                 </li>
118                 <li>
119                     <a href="">关于</a>
120                 </li>
121                 <li>
122                     <a href="">商业合作</a>
123                 </li>
124             </ul>
125         </li>
126     </ul>
127     <script>
128         // 1. 获取元素
129         var nav = document.querySelector('.nav');
130         var lis = nav.children; // 得到4个小li
131         // 2.循环注册事件
132         for (var i = 0; i < lis.length; i++) {
133             lis[i].onmouseover = function() {
134                 this.children[1].style.display = 'block';
135             };
136             lis[i].onmouseout = function() {
137                 this.children[1].style.display = 'none';
138             }
139         }
140     </script>
141 </body>
142 
143 </html>
下拉菜单案例

兄弟节点

1. node.nextSibling
nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
2. node.previousSibling
previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
 
3. node.nextElementSibling
nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
4. node.previousElementSibling
previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。
注意:这两个方法有兼容性问题, IE9 以上才支持。
 
如何解决兼容性问题 ?
自己封装一个兼容性的函数。
function getNextElementSibling(element) {
  var el = element;
  while (el = el.nextSibling) {
    if (el.nodeType === 1) { //注意这里的条件的写法,是一个赋值语句
      return el;
    }
  }
  return null;
}

5.3 创建节点

document.createElement('tagName')
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。

5.4 添加节点

1. node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的after 伪元素。
2. node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before伪元素。
 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7     <style>
 8         * {
 9             margin: 0;
10             padding: 0;
11         }
12         
13         body {
14             padding: 100px;
15         }
16         
17         textarea {
18             width: 200px;
19             height: 100px;
20             border: 1px solid pink;
21             outline: none;
22             resize: none;
23         }
24         
25         ul {
26             margin-top: 50px;
27         }
28         
29         li {
30             width: 300px;
31             padding: 5px;
32             background-color: rgb(245, 209, 243);
33             color: red;
34             font-size: 14px;
35             margin: 15px 0;
36         }
37     </style>
38 </head>
39 
40 <body>
41     <textarea name="" id=""></textarea>
42     <button>发布</button>
43     <ul>
44 
45     </ul>
46     <script>
47         // 1. 获取元素
48         var btn = document.querySelector('button');
49         var text = document.querySelector('textarea');
50         var ul = document.querySelector('ul');
51         // 2. 注册事件
52         btn.onclick = function() {
53             if (text.value === '') {
54                 alert('您没有输入内容');
55                 return false;
56             } else {
57                 // console.log(text.value);
58                 // (1) 创建元素
59                 var li = document.createElement('li');
60                 // 先有li 才能赋值
61                 li.innerHTML = text.value;
62                 // (2) 添加元素
63                 // ul.appendChild(li);
64                 ul.insertBefore(li, ul.children[0]);
65             }
66         }
67     </script>
68 </body>
69 
70 </html>
发布留言案例

5.5 删除节点

node.removeChild(child)
node.removeChild() 方法从 DOM 中删除一个子节点,返回删除的节点。
 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7 </head>
 8 <body>
 9     <button>删除</button>
10     <ul>
11         <li>熊大</li>
12         <li>熊二</li>
13         <li>光头强</li>
14     </ul>
15     <script>
16         // 1.获取元素
17         var ul = document.querySelector('ul');
18         var btn = document.querySelector('button');
19         // 2. 删除元素  node.removeChild(child)
20         // ul.removeChild(ul.children[0]);
21         // 3. 点击按钮依次删除里面的孩子
22         btn.onclick = function() {
23             if (ul.children.length == 0) {
24                 this.disabled = true;
25             } else {
26                 ul.removeChild(ul.children[0]);
27             }
28         }
29     </script>
30 </body>
31 
32 </html>
删除节点
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7     <style>
 8         * {
 9             margin: 0;
10             padding: 0;
11         }
12         body {
13             padding: 100px;
14         }
15         textarea {
16             width: 200px;
17             height: 100px;
18             border: 1px solid pink;
19             outline: none;
20             resize: none;
21         }
22         ul {
23             margin-top: 50px;
24         }
25         li {
26             width: 300px;
27             padding: 5px;
28             background-color: rgb(245, 209, 243);
29             color: red;
30             font-size: 14px;
31             margin: 15px 0;
32         }
33         li a {
34             float: right;
35         }
36     </style>
37 </head>
38 
39 <body>
40     <textarea name="" id=""></textarea>
41     <button>发布</button>
42     <ul>
43 
44     </ul>
45     <script>
46         // 1. 获取元素
47         var btn = document.querySelector('button');
48         var text = document.querySelector('textarea');
49         var ul = document.querySelector('ul');
50         // 2. 注册事件
51         btn.onclick = function() {
52             if (text.value == '') {
53                 alert('您没有输入内容');
54                 return false;
55             } else {
56                 // console.log(text.value);
57                 // (1) 创建元素
58                 var li = document.createElement('li');
59                 // 先有li 才能赋值
60                 li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";
61                 // (2) 添加元素
62                 // ul.appendChild(li);
63                 ul.insertBefore(li, ul.children[0]);
64                 // (3) 删除元素 删除的是当前链接的li  它的父亲
65                 var as = document.querySelectorAll('a');
66                 for (var i = 0; i < as.length; i++) {
67                     as[i].onclick = function() {
68                         // node.removeChild(child); 删除的是 li 当前a所在的li  this.parentNode;
69                         ul.removeChild(this.parentNode);
70                     }
71                 }
72             }
73         }
74     </script>
75 </body>
76 
77 </html>
删除留言案例

 

5.6 复制节点

node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
注意:
1. 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
2. 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。
 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8 <ul>
 9     <li>雯雯</li>
10     <li>菲菲</li>
11     <li>颖颖</li>
12 </ul>
13 <script>
14     var ul = document.querySelector('ul');
15     //var li = ul.children[0].cloneNode();//括号里为空或者false,则是浅拷贝,只复制标签
16     var li = ul.children[0].cloneNode(true);//括号里为true,则是深拷贝
17     ul.appendChild(li);
18 </script>
19 </body>
20 </html>
复制节点案例
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7     <style>
 8         table {
 9             width: 500px;
10             margin: 100px auto;
11             border-collapse: collapse;
12             text-align: center;
13         }
14         td,
15         th {
16             border: 1px solid #333;
17         }
18 
19         thead tr {
20             height: 40px;
21             background-color: #ccc;
22         }
23     </style>
24 </head>
25 
26 <body>
27     <table cellspacing="0">
28         <thead>
29             <tr>
30                 <th>姓名</th>
31                 <th>科目</th>
32                 <th>成绩</th>
33                 <th>操作</th>
34             </tr>
35         </thead>
36         <tbody>
37 
38         </tbody>
39     </table>
40     <script>
41         // 1.先去准备好学生的数据
42         var datas = [{
43             name: '魏璎珞',
44             subject: 'JavaScript',
45             score: 100
46         }, {
47             name: '弘历',
48             subject: 'JavaScript',
49             score: 98
50         }, {
51             name: '傅恒',
52             subject: 'JavaScript',
53             score: 99
54         }, {
55             name: '明玉',
56             subject: 'JavaScript',
57             score: 88
58         }, {
59             name: '大猪蹄子',
60             subject: 'JavaScript',
61             score: 0
62         }];
63         // 2. 往tbody 里面创建行: 有几个人(通过数组的长度)我们就创建几行
64         var tbody = document.querySelector('tbody');
65         for (var i = 0; i < datas.length; i++) { // 外面的for循环管行 tr
66             // 1. 创建 tr行
67             var tr = document.createElement('tr');
68             tbody.appendChild(tr);
69             // 2. 行里面创建单元格(跟数据有关系的3个单元格) td 单元格的数量取决于每个对象里面的属性个数  for循环遍历对象 datas[i]
70             for (var k in datas[i]) { // 里面的for循环管列 td
71                 // 创建单元格
72                 var td = document.createElement('td');
73                 // 把对象里面的属性值 datas[i][k] 给 td
74                 // console.log(datas[i][k]);
75                 td.innerHTML = datas[i][k];
76                 tr.appendChild(td);
77             }
78             // 3. 创建有删除2个字的单元格
79             var td = document.createElement('td');
80             td.innerHTML = '<a href="javascript:;">删除 </a>';
81             tr.appendChild(td);
82         }
83         // 4. 删除操作 开始
84         var as = document.querySelectorAll('a');
85         for (var i = 0; i < as.length; i++) {
86             as[i].onclick = function() {
87                 // 点击a 删除 当前a 所在的行(链接的爸爸的爸爸)  node.removeChild(child)
88                 tbody.removeChild(this.parentNode.parentNode)
89             }
90         }
91         // for(var k in obj) {
92         //     k 得到的是属性名
93         //     obj[k] 得到是属性值
94         // }
95     </script>
96 </body>
97 
98 </html>
动态生成表格案例

 

5.7 三种动态创建元素方式的区别

区别:
1. document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘。弃之。
2. innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘。
3. innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂。
  采取字符串拼接则由于字符串不可变,每次拼接都会向系统申请新内存空间存储写入数据导致耗时较长,而数组可变,用数组则耗时很短。比createElement()的耗时还短如果数据量大的话。
4. createElement() 创建多个元素效率稍低一点点,但是结构更清晰。
 
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7 </head>
 8 
 9 <body>
10     <button>点击</button>
11     <p>abc</p>
12     <div class="inner"></div>
13     <div class="create"></div>
14     <script>
15         // window.onload = function() {
16         //         document.write('<div>123</div>');
17 
18         //     }
19         // 三种创建元素方式区别
20         // 1. document.write() 创建元素  如果页面文档流加载完毕,再调用这句话会导致页面重绘
21         // var btn = document.querySelector('button');
22         // btn.onclick = function() {
23         //     document.write('<div>123</div>');
24         // }
25 
26         // 2. innerHTML 创建元素
27         var inner = document.querySelector('.inner');
28         // for (var i = 0; i <= 100; i++) {
29         //     inner.innerHTML += '<a href="#">百度</a>' //字符串拼接耗时长
30         // }
31         var arr = [];
32         for (var i = 0; i <= 100; i++) {
33             arr.push('<a href="#">百度</a>');
34         }
35         inner.innerHTML = arr.join('');
36         // 3. document.createElement() 创建元素
37         var create = document.querySelector('.create');
38         for (var i = 0; i <= 100; i++) {
39             var a = document.createElement('a');
40             create.appendChild(a);
41         }
42     </script>
43 </body>
44 
45 </html>
创建元素的区别

 

posted @ 2020-06-12 20:05  天青色wy  阅读(342)  评论(1编辑  收藏  举报