DOM——文档对象模型

DOM 的概念

• 文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言的标准编程接口。它是一种与平台和语言无关的应用程序接口(API),它可以动态地访问程序和脚本,更新其内容、结构和 www 文档的风格(目前,HTML 和 XML 文档是通过说明部分定义的)。文档可以进一步被处理,处理的结果可以加入到当前的页面。DOM 是一种基于树的 API 文档,它要求在处理过程中整个文档都表示在存储器中。

DOM 树

• DOM 又称为文档树模型
• - 文档:一个网页可以称为文档
• - 节点:网页中的所有内容都是节点(标签、属性、文本、注释等)
• - 元素:网页中的标签
• - 属性:标签的属性
在这里插入图片描述

DOM 经常进行的操作

• 获取元素
• 对元素进行操作(设置其属性或调用其方法)
• 动态创建元素
• 事件(什么时机做相应的操作)

DOM 获取页面元素

获取页面元素

• 为什么要获取页面元素?
• 例如:我们想要操作页面上的某部分(显示/隐藏,动画),需要先获取到该部分对应的元素,才进行后续操作。

根据 id 获取元素

• 方法:调用 document 对象的 getElementById 方法。
• 参数:字符串类型的 id 的属性值。
• 返回值:对应 id 名的元素对象。
• 注意1:由于 id 名具有唯一性,部分浏览器支持直接使用 id 名访问元素,但不是标准方式,不推荐使用。
• 注意2:代码执行顺序,如果 js 在 html 结构之前,会导致结构未加载,不能获取对应id的元素。
• 注意3:id名具有唯一性,同时书写两个相同的id名,只会执行第一个。在这里插入图片描述
在这里插入图片描述

根据标签名获取元素

• 方法:调用 document 对象的 getElementsByTagName 方法。
• 参数:字符串类型的标签名。
• 返回值:同名的元素对象组成的数组。
• 注意1:操作数据时需要按照操作数组的方法进行。
• 注意2:getElementsByTagName 方法内部获取的元素是动态增加的。

在这里插入图片描述在这里插入图片描述

元素对象内部获取标签元素

• 获取的元素对象内部,本身也可以调用根据标签获取元素方法,例如 div 元素对象也可以调用 getElementsByTagName 方法。
• 目的:缩小选择元素的范围,类似 css 中的后代选择器

在这里插入图片描述在这里插入图片描述

根据 name 获取元素

• 方法:调用 document 对象的 getElementsByName 方法。
• 参数:字符串类型的 name 属性值。
• 返回值:name 属性值相同的元素对象组成的数组。
• 不建议使用:在 IE 和 Opera 中有兼容问题,会多选中 id 属性值相同的元素。

Nodelist :节点(标签、属性、文本、注释等) 列表集合,类数组
方法选中的元素也是动态变化的
在这里插入图片描述在这里插入图片描述

根据类名获取元素

• 方法:调用 document 对象的 getElementsByClassName 方法。
• 参数:字符串类型的 class 属性值。
• 返回值:class 属性值相同的元素对象组成的数组。
• 浏览器兼容问题:不支持 IE8 及以下的浏览器

方法选中的元素也是动态变化的
在这里插入图片描述在这里插入图片描述

根据选择器获取元素

• 方法1:调用 document 对象的 querySelector 方法,通过 css 中的选择器去选取第一个符合条件的标签元素。
• 方法2:调用 document 对象的 querySelectorAll 方法,通过 css 中的选择器去选取所有符合条件的标签元素。
• 参数:字符串类型的 css 中的选择器。
• 浏览器兼容问题:不支持 IE8 以下的浏览

必须在结构加载完成后书写,不能写在前面。
在这里插入图片描述

在这里插入图片描述

总结

掌握,没有兼容问题
• getElementById()
• getElementsByTagName()
了解
• getElementsByName()
• getElementsByClassName()
• querySelector()
• querySelectorAll()

DOM 事件基本应用

事件

• 事件:在什么时候做什么事
• 执行机制:触发–响应机制
• 绑定事件(注册事件)三要素:
1、事件源:给谁绑定事件
2、事件类型:绑定什么类型的事件 click 单击
3、事件函数:事件发生后执行什么内容,写在函数内部

事件监听

• JavaScript 解析器会给有绑定事件的元素添加一个监听,解析器会一直监测这个元素,只要触发对应的绑定事件,会立刻执行事件函数。

常用事件监听方法

• 方法1:绑定 HTML 元素属性。
• 方法2:绑定 DOM 对象属性

常用的鼠标事件类型

• onclick 鼠标左键单击触发
• ondbclick 鼠标左键双击触发
• onmousedown 鼠标按键按下触发
• onmouseup 鼠标按键放开时触发
• onmousemove 鼠标在元素上移动触发
• onmouseover 鼠标移动到元素上触发
• onmouseout 鼠标移出元素边界触发

案例:
• 点击按钮弹出提示框
在这里插入图片描述
在这里插入图片描述

DOM 元素属性操作

非表单元素的属性

• 例如:href、title、id、src 等。
• 调用方式:元素对象打点调用属性名,例如 obj.href。
• 注意:部分的属性名跟关键字和保留字冲突,会更换写法。

  • class → className
  • for → htmlFor
  • rowspan → rowSpan

• 属性赋值:给元素属性赋值,等号右侧的赋值都是字符串格式。
在这里插入图片描述在这里插入图片描述

案例
•点击按钮切换图片

在这里插入图片描述请添加图片描述

• 点击按钮显示隐藏 div

在这里插入图片描述

请添加图片描述

• 美女相册

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
请添加图片描述

获取标签内部内容的属性

• 获取标签内部内容的属性有两个:innerHTML 和 innerText
• innerHTML属性,在获取标签内部内容时,如果包含标签,获取的内容会包含标签,获取的
内容包括空白换行等。
• innerText属性,在获取标签内部内容时,如果包含标签,获取的内容会过滤标签,获取的
内容会去掉换行和缩进等空白。

更改标签内容

还可以通过两个属性给双标签内部去更改内容:
• innerHTML 设置属性值,有标签的字符串,会按照 HTML 语法中的标签加载。
• innerText 设置属性值,有标签的字符串,会按照普通的字符加载。
对比使用场景
• innerText:在设置纯字符串时使用。
• innerHTML:在设置有内部子标签结构时使用。
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

表单元素属性

• value 用于大部分表单元素的内容获取(option除外)
• type 可以获取input标签的类型(输入框或复选框等)
• disabled 禁用属性
• checked 复选框选中属性
• selected 下拉菜单选中属性
• 注意:在 DOM 中元素对象的属性值只有一个时,会被转成布尔值显示。
例如:txt.disabled = true;

在这里插入图片描述

在这里插入图片描述

案例

• 检测用户名是否是3-6位,密码是否是6-8位,如果不满足要求高亮显示文本框

在这里插入图片描述

请添加图片描述

• 设置下拉框中的选中项

在这里插入图片描述

请添加图片描述

• 搜索文本框

在这里插入图片描述

请添加图片描述

• 全选反选
<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
        
        .wrap {
            width: 300px;
            margin: 100px auto 0;
        }
        
        table {
            border-collapse: collapse;
            border-spacing: 0;
            border: 1px solid #c0c0c0;
            width: 300px;
        }
        
        th,
        td {
            border: 1px solid #d0d0d0;
            color: #404060;
            padding: 10px;
        }
        
        th {
            background-color: #09c;
            font: bold 16px "微软雅黑";
            color: #fff;
        }
        
        td {
            font: 14px "微软雅黑";
        }
        
        tbody tr {
            background-color: #f0f0f0;
        }
        
        tbody tr:hover {
            cursor: pointer;
            background-color: #fafafa;
        }
    </style>

</head>

<body>
    <div class="wrap">
        <table>
            <thead>
                <tr>
                    <th>
                        <input type="checkbox" id="all" />
                    </th>
                    <th>商品</th>
                    <th>价钱</th>
                </tr>
            </thead>
            <tbody id="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>
        <input type="button" value="  反 选  " id="btn">
    </div>
    <script>
        // 获取元素
        var all = document.getElementById("all");
        var tb = document.getElementById("tb");
        var btn = document.getElementById("btn");
        var tb_inputs = tb.getElementsByTagName("input");

        // 1.全选:让子选项的选择效果始终与全选保持一致
        all.onclick = function() {
            // 遍历所有的子选项
            for (var i = 0; i < tb_inputs.length; i++) {
                // 让每一个子选项的 checked 属性值与全选保持一致
                tb_inputs[i].checked = all.checked;
            }
        };
        // 2.单独选择子选项过程
        // 给每一次点击任何一个子选项进行判断
        for (var i = 0; i < tb_inputs.length; i++) {
            tb_inputs[i].onclick = function() {
                // 需要判断所有的子选项是否都是选中的状态,如果都选中,让全选被选中,如果有的没有被选中,让全选取消选择
                allChecked();
            }
        }
        // 3.反选
        btn.onclick = function() {
            // 让所有子选项与之前的状态相反
            for (var i = 0; i < tb_inputs.length; i++) {
                // 让属性值取原来相反的值
                tb_inputs[i].checked = !tb_inputs[i].checked;
            }
            // 控制全选效果,也需要进行取反
            allChecked();
        };
        // 定义一个 all 是否被选中的函数
        function allChecked() {
            // 使用一个中间过渡变量,初始认为所有的子选项都是被选中的
            var isAllChecked = true;
            // 遍历所有子选项,进行判断
            for (var j = 0; j < tb_inputs.length; j++) {
                // 一旦有一个是没有被选择的,让变量变为 false
                if (tb_inputs[j].checked === false) {
                    isAllChecked = false;
                    // 只要走到这里,说明肯定不是全选,不需要往下执行循环
                    break;
                }
            }
            // 如果循环内部条件永远不成立,说明所有子选项都是被选中,isAllChecked 的值没有发生变化,还是 true
            // 给 all 元素设置 checked 属性
            all.checked = isAllChecked;
        }
    </script>
</body>

</html>

请添加图片描述

自定义属性操作

• getAttribute(name) 获取标签行内属性
• setAttribute(name,value) 设置标签行内属性
• removeAttribute(name) 移除标签行内属性
• 与element.属性的区别: 上述三个方法用于获取任意的行内属性,包括自定义的属性。
在这里插入图片描述

style 样式属性操作

• 使用 style 属性方式设置的样式显示在标签行内。
• element.style 属性的值,是所有行内样式组成的一个样式对象。
• 样式对象可以继续点语法调用或更改 css 的行内样式属性,例如 width、height 等属性。
• 注意1:类似 background-color 这种复合属性的单一属性写法,是由多个单词组成的,要
修改为驼峰命名方式书写 backgroundColor。
• 注意2:通过样式属性设置宽高、位置的属性类型是字符串,需要加上 px 等单位。

在这里插入图片描述

className 类名属性操作

• 修改元素的 className 属性相当于直接修改标签的类名。
• 如果需要修改多条 css 样式,可以提前将修改后的样式设置到一个类选择器中,后续通过
修改类名的方式,批量修改 css 样式。
在这里插入图片描述

案例

• 开关灯
function my$(id) {
    return document.getElementById(id);
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="button" value="关灯" id="btn">
  <script src="common.js"></script>
  <script>
    // 获取元素
    var btn = my$("btn");
    // console.log(btn);
    // 定义一个判断变量,true 表示开灯状态,false 表示关灯状态
    // var isOpen = true;
    // 点击事件,控制 body 的背景
    btn.onclick = function () {
      // 开灯时,需要点击后让它关灯并切换文字为 开灯
      // if (isOpen) {
      //   document.body.style.backgroundColor = "black";
      //   this.value = "开灯";
      //   isOpen = false;
      // } else {
      //   document.body.style.backgroundColor = "white";
      //   this.value = "关灯";
      //   isOpen = true;
      // }
      // 直接使用 btn 的 value 值进行判断
      if (this.value === "关灯") {
        document.body.style.backgroundColor = "black";
        this.value = "开灯";
      } else {
        document.body.style.backgroundColor = "white";
        this.value = "关灯";
      }
    };
  </script>
</body>
</html>

请添加图片描述

• 显示隐藏二维码


<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .box {
            width: 50px;
            height: 50px;
            background: url(images/bgs.png) no-repeat -159px -51px;
            position: fixed;
            right: 10px;
            top: 40%;
        }
        .erweima {
            position: absolute;
            top: 0;
            left: -150px;
        }
        .box a {
            display: block;
            width: 50px;
            height: 50px;
        }
        .hide {
            display: none;
        }
        .show {
            display: block;
        }
    </style>
</head>
<body>
    <div class="box" id="box">
        <div class="erweima hide" id="er">
            <img src="images/456.png" alt=""/>
        </div>
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var box = my$("box");
        var er = my$("er");
        // 给 box 添加鼠标移上事件 onmouseover ,添加鼠标离开事件 onmouseout
        box.onmouseover = function () {
            // 让子级元素进行显示,就是将 hide 改为 show
            // er.className = "erweima show";
            er.className = er.className.replace("hide","show");
        };
        box.onmouseout = function () {
            // 让子级元素进行隐藏,就是将 show 改为 hide
            // er.className = "erweima hide";
            er.className = er.className.replace("show","hide");
        };
    </script>
</body>
</html>

请添加图片描述

• 当前输入的文本框高亮显示
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <button id="btn">按钮</button>
    <script>
        // 获取元素
        var txts = document.getElementsByTagName("input");
        // 添加批量的获取焦点事件
        for (var i = 0; i < txts.length; i++) {
            // 排他思想:1.排除其他 2.保留自己         

            // 给每一个input标签添加获取焦点事件
            txts[i].onfocus = function() {
                // 排除其他的方法:将所有的项包含自己都设置为默认样式
                // 遍历数组,让所有的样式恢复默认
                for (var j = 0; j < txts.length; j++) {
                    txts[j].style.backgroundColor = "";
                }
                // 设置元素自己高亮显示
                // 保留自己的特殊样式
                // this 指代事件源自己
                this.style.backgroundColor = "yellow";
            };
        }
    </script>
</body>

</html>

请添加图片描述

• 点击按钮改变div的大小和位置
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 100px;
            height: 100px;
            background-color: pink;
        }
        
        .new {
            position: absolute;
            width: 200px;
            height: 200px;
            left: 200px;
            top: 200px;
        }
    </style>
</head>

<body>
    <input type="button" value="按钮" id="btn">
    <div id="box"></div>
    <script src="common.js"></script>
    <script>
        //获取元素
        var btn = my$("btn");
        var box = my$("box");
        // 添加事件
        btn.onclick = function() {
            // 修改类名
            // box.className = "new";
            // 修改 style 样式对象中的属性
            box.style.width = "200px";
            box.style.height = "200px";
            box.style.left = "200px";
            box.style.top = "200px";
            box.style.position = "absolute";
        };
    </script>
</body>

</html>

请添加图片描述

• 表格隔行变色、高亮显示
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        td {
            width: 100px;
            height: 40px;
        }
    </style>
</head>

<body>
    <table border="1" style="border-collapse: collapse;">
        <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>
        <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>
    </table>
    <script>
        // 获取所有的行
        var trs = document.getElementsByTagName("tr");
        // 1.隔行变色
        for (var i = 0; i < trs.length; i++) {
            // 下标为偶数的行显示粉色
            // 下标为奇数的行显示灰色
            if (i % 2 == 0) {
                trs[i].style.backgroundColor = "pink";
            } else {
                trs[i].style.backgroundColor = "lightgray";
            }
            // 2.鼠标移上高亮显示,鼠标离开恢复默认
            // 全局变量
            var bgc;
            // 鼠标移上高亮显示
            trs[i].onmouseover = function() {
                // 定义变量记录 tr 原来的颜色
                bgc = this.style.backgroundColor;
                this.style.backgroundColor = "skyblue";
            };
            // 鼠标离开恢复默认
            trs[i].onmouseout = function() {
                this.style.backgroundColor = bgc;
            };
        }
    </script>
</body>

</html>

请添加图片描述

• tab选项卡切换

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {margin:0; padding: 0;}
        ul {
            list-style-type: none;
        }
        .box {
            width: 400px;
            height: 300px;
            border: 1px solid #ccc;
            margin: 100px auto;
            overflow: hidden;
        }
        .hd {
            height: 45px;
        }
        .hd span {
            display:inline-block;
            width: 90px;
            background-color: pink;
            line-height: 45px;
            text-align: center;
            cursor: pointer;
        }
        .hd span.current {
            background-color: skyblue;
        }
        .bd div {
            height: 255px;
            background-color: skyblue;
            display: none;
        }
        .bd div.current {
            display: block;
        }
    </style>

</head>
<body>
    <div class="box">
        <div class="hd" id="hd">
            <span class="current">体育</span>
            <span>娱乐</span>
            <span>新闻</span>
            <span>综合</span>
        </div>
        <div class="bd" id="bd">
            <div class="current">我是体育模块</div>
            <div>我是娱乐模块</div>
            <div>我是新闻模块</div>
            <div>我是综合模块</div>
        </div>
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var hd = my$("hd");
        var spans = hd.getElementsByTagName("span");
        var bd = my$("bd");
        var divs = bd.getElementsByTagName("div");
        // 鼠标移上某个 span 让它添加一个类名,其他的失去类名
        for (var i = 0 ; i < spans.length ; i++) {
            // 给每一个 span 元素添加一个新的属性,记录自己在数组中的下标
            spans[i].index = i;
            spans[i].onmouseover = function () {
                // console.dir(this);
                // 1.让 span 自己进行切换
                // 排他思想:
                // 排除其他
                for (var j = 0; j < spans.length ; j++) {
                    spans[j].className = "";
                    // 由于 divs 中数据个数与 spans 一样,所以可以再同一个遍历循环中,进行排他操作
                    divs[j].className = "";
                }
                // 保留自己
                this.className = "current";
                // console.log(this.index);
                // 2.让 bd 中的 div 也对应进行切换
                // 对应控制思想:有两组数据中存储了相同个数的元素对象,一组对象的变化,会引起另外一组的变化
                // 实现方法:找两个数据中的共同点,两个数组中元素对象的下标是一样的
                // 对应控制中也会涉及到排他的操作
                // 保留 div 自己的类名
                divs[this.index].className = "current";
            };
        }

    </script>
</body>
</html>

请添加图片描述

DOM 节点操作

节点属性

• nodeType 节点的类型,属性值为数字,表示不同的节点类型,共 12 种,只读
1 元素节点
2 属性节点
3 文本节点
• nodeName 节点的名称(标签名称),只读
• nodeValue 节点值,返回或设置当前节点的值
元素节点的 nodeValue 始终是 null
在这里插入图片描述

父子节点常用属性

• childNodes 只读属性,获取一个节点所有子节点的实时的集合,集合是动态变化的。
• children 只读属性,返回一个节点所有的子元素节点集合,是一个动态更新的 HTML 元素
集合。
• firstChild 只读属性,返回该节点的第一个子节点,如果该节点没有子节点则返回 null。
• lastChild 只读属性,返回该节点的最后一个子节点,如果该节点没有子节点则返回 null。
• parentNode 返回一个当前节点的父节点,如果没有这样的节点,比如说像这个节点是树结构
的顶端或者没有插入一棵树中,这个属性返回 null。
• parentElement 返回当前节点的父元素节点,如果该元素没有父节点,或者父节点不是一个 DOM
元素,则返回 null
在这里插入图片描述

兄弟节点常用属性

• nextSibling 只读属性,返回与该节点同级的下一个节点,如果没有返回null。
• previousSibling 只读属性,返回与该节点同级的上一个节点,如果没有返回null。
• nextElementSibling 只读属性,返回与该节点同级的下一个元素节点,如果没有返回null。
• previousElementSibling 只读属性,返回与该节点同级的上一个元素节点,如果没有返回null。
• 注意:nextElementSibling 和 previousElementSibling 有兼容性问题,IE9以后才支持。

在这里插入图片描述

创建新节点的方法

• document.createElement(“div”) 创建元素节点
• document.createAttribute(“id”) 创建属性节点
• document.createTextNode(“hello”) 创建文本节点
• 一般将创建的新节点存在变量中,方便使用。
在这里插入图片描述

节点常用操作方法 1

• parentNode.appendChild(child):将一个节点添加到指定父节点的子节点列表末尾。
• parentNode.replaceChild(newChild, oldChild):用指定的节点替换当前节点的一个子节
点,并返回被替换掉的节点。
• parentNode.insertBefore(newNode, referenceNode):在参考节点之前插入一个拥有指定
父节点的子节点,referenceNode 必须设置,如果 referenceElement 为 null 则 newNode
将被插入到子节点的末尾。
• parentNode.removeChild(child):移除当前节点的一个子节点。这个子节点必须存在于当
前节点中。
在这里插入图片描述在这里插入图片描述

节点常用操作方法 2

• Node.cloneNode():克隆一个节点,并且可以选择是否克隆这个节点下的所有内容。参数为
Boolean 布尔值,表示是否采用深度克隆,如果为 true,则该节点的所有后代节点也都会被
克隆,如果为 false,则只克隆该节点本身,默认值为 true,节点下的内容会被克隆。
• 注意:克隆时,标签上的属性和属性值也会被复制,写在标签行内的绑定事件可以被复制,
但是通过。

在这里插入图片描述

节点常用操作方法 3

• Node.hasChildNodes():没有参数,返回一个 Boolean 布尔值,来表示该元素是否包含有
子节点。
• Node.contains(child):返回一个 Boolean 布尔值,来表示传入的节点是否为该节点的后
代节点。
在这里插入图片描述

判断方法总结

• 有三种方法可以判断当前节点是否有子节点。
• node.firstChild !== null
• node.childNodes.length > 0
• node.hasChildNodes()

案例应用

• 动态创建列表

在这里插入图片描述

在这里插入图片描述

• 动态创建表格
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    table{
        border-collapse: collapse;
    }
    thead{
        background-color: #ccc;
    }
    th,td{
        width: 100px;
        height: 40px;
        text-align: center;
    }
  </style>
</head>
<body>
  <h1>动态创建表格</h1>
  <table id="wrap" border="1">
    <thead>
      <tr>
        <th>姓名</th>
        <th>科目</th>
        <th>成绩</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody id="tb">

    </tbody>
  </table>
  <script src="common.js"></script>
  <script>
    // 获取元素
    var tb = my$("tb");
    // 模拟后台传输的数据
    var datas = [
      {name: "zs",subject: "语文",score: 80},
      {name: "ls",subject: "数学",score: 87},
      {name: "ww",subject: "英语",score: 90},
      {name: "lb",subject: "物理",score: 89},
      {name: "cc",subject: "生物",score: 100},
      {name: "sq",subject: "化学",score: 98}
    ];
    // 根据数组中的数据个数生成对应个数的 tr 
    // 将生成 tr 添加到 tbody 中
    // 数组遍历
    for (var i = 0 ; i < datas.length ; i++) {
      // 每一个数据都要生成一个 tr
      var tr = document.createElement("tr");
      // 添加到 tb 中
      tb.appendChild(tr);
      // 每一个 tr 中还需要添加对应的 td 
      // 每一行 内部的 td 中的数据来自于 数组的每一项
      var data = datas[i]; //{name: "zs",subject: "语文",score: 80}
      // 遍历 data 对象,根据它的项数来确定添加的 td 的个数
      for (var k in data) {
        // 生成一个 td
        var td = document.createElement("td");
        // 添加到 tr 中去
        tr.appendChild(td);
        // 添加给每一个 td 数据
        td.innerText = data[k];
      }
      // 除了前面动态获取的数据 td 之外,还要添加一个删除的 td
      td = document.createElement("td");
      // 添加到 tr 中去
      tr.appendChild(td);
      // 最后一个 td 中需要添加一个 a 标签
      var a = document.createElement("a");
      a.innerText = "删除";
      a.href = "javascript:void(0);"
      // 将 a 添加到 td 中
      td.appendChild(a);
      // 给生成的每个 a 添加一个点击事件,移除当前所在的行
      a.onclick = function () {
        // 找到所在的行的 tr
        // this.parentNode.parentNode
        // 从 tbody 中移除对应的 tr
        tb.removeChild(this.parentNode.parentNode);
      };
    }
  </script>
</body>
</html>

在这里插入图片描述

• 选择水果
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        select {
            width: 200px;
            height: 200px;
            background-color: #33cccc;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <select id="all" size="5" multiple="multiple">
    <option>苹果</option>
    <option>橘子</option>
    <option></option>
    <option>西瓜</option>
    <option>水蜜桃</option>
  </select>

    <input type="button" value=">>" id="btn1">
    <input type="button" value="<<" id="btn2">
    <input type="button" value=">" id="btn3">
    <input type="button" value="<" id="btn4">

    <select id="choose" multiple="multiple">
  </select>

    <script src="common.js"></script>
    <script>
        // 获取元素
        var all = my$("all");
        var choose = my$("choose");
        var btn1 = my$("btn1");
        var btn3 = my$("btn3");
        // 给第一个按钮添加点击事件,让 all 中的所有子元素移动到 choose 中
        btn1.onclick = function() {
            var opts = all.children; //内部的元素时动态添加的
            // 获取 all 中所有的子元素
            // 获取最开始的数组的个数
            var n = opts.length;
            // console.log(n);
            // 将所有的 opts 中的元素添加给 choose
            for (var i = 0; i < n; i++) {
                choose.appendChild(opts[0]);
            }
        };

        // 单选移动
        btn3.onclick = function() {
            var opts = all.children; //内部的元素时动态添加的
            // 移动的内容希望可以是固定的一个数组中的项
            var arr = [];
            // 通过判断条件,往 arr 中添加需要移动的元素
            for (var i = 0; i < opts.length; i++) {
                if (opts[i].selected === true) {
                    arr.push(opts[i]);
                }
            }
            // 对需要移动的固定数组进行遍历
            for (var j = 0; j < arr.length; j++) {
                choose.appendChild(arr[j]);
                arr[j].selected = false;
            }

        };
    </script>
</body>

</html>

请添加图片描述

DOM 事件详解

注册事件的其他方法1

• element.addEventListener() 方法。
• 参数:
第一个参数:事件类型的字符串(直接书写”click”,不需要加 on)
第二个参数:事件函数
• 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
• 兼容性问题:不支持 IE9 以下的浏览器
在这里插入图片描述

注册事件的其他方法2

• element.attachEvent() 方法。
• 参数:
第一个参数:事件类型的字符串(需要加 on)
第二个参数:事件函数
• 同一个元素可以多次绑定事件监听,同一个事件类型可以注册多个事件函数
• 兼容性问题:只支持 IE10 及以下的浏览器。
在这里插入图片描述

注册事件的兼容写法

• 自定义一个注册事件函数
• 参数:事件源,事件类型(不加 on),事件函数
• IE9 及以上的浏览器,使用 addEventListener 方法
• IE9 以下的浏览器,使用 attachEvent 方法
• 判断浏览器时,不需要判断它的版本,可以检测浏览器能力
• 浏览器能力检测:将某个方法的调用作为 if 语句的判断条件,如果浏览器认识该方法返回
true,否则返回 false。
在这里插入图片描述

移除事件的其他方法1

• element.removeEventListener() 方法。
• 参数:
第一个参数:事件类型的字符串(直接书写”click”,不需要加 on)
第二个参数:事件函数引用名
• 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
• 兼容性问题:不支持 IE9以下的浏览器

移除事件的其他方法2

• element.detachEvent() 方法。
• 参数:
第一个参数:事件类型的字符串(需要加 on)
第二个参数:事件函数
• 注意:没有办法移除一个匿名函数,所以在注册事件时需要单独声明一个有函数名的事件函数。
兼容性问题:只支持 IE10 及以下的浏览器
在这里插入图片描述

移除事件的兼容写法

• 自定义一个移除事件函数
• 参数:事件源,事件类型(不加 on),事件函数
• IE9 及以上的浏览器,使用 removeEventListener 方法
• IE9 以下的浏览器,使用 detachEvent 方法
• 建议:将自己封装的一些常用函数和方法,放到一个单独的 .js 文件中
在这里插入图片描述

DOM 事件流

在这里插入图片描述

事件流的三个阶段

• 第一个阶段:事件捕获
• 第二个阶段:事件执行过程
• 第三个阶段:事件冒泡请添加图片描述

• addEventListener() 第三个参数为 false 时,事件冒泡
• addEventListener() 第三个参数为 true 时,事件捕获
• onclick 类型:只能进行事件冒泡过程,没有捕获阶段
• attachEvent() 方法:只能进行事件冒泡过程,没有捕获阶段
在这里插入图片描述

事件委托

• 利用事件冒泡,将子级的事件委托给父级加载
• 同时,需要利用事件函数的一个 e 参数,内部存储的是事件对象

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul {
            width: 300px;
            border: 1px dashed #f0f;
            margin: 50px auto;
            font-size: 24px;
            line-height: 48px;
            list-style: none;
        }
        li {
            padding-left: 20px;
            cursor: pointer;
        }

    </style>
</head>

<body>
    <ul id="list">
        <li>刘亦菲</li>
        <li>杨幂</li>
        <li>唐嫣</li>
        <li>赵丽颖</li>
        <li>刘诗诗</li>
    </ul>
    <script>
        // 让每个 li 被点击后,自己添加特殊的背景色,而其他兄弟不添加
        // 以前的思路:获取所有的 li 标签元素,批量添加事件
        // 事件委托:可以将一些子级的公共类型的事件委托给他们的父级添加,在父级内部想办法找到真正触发事件的最底层的事件源
        // 获取元素
        var list = document.getElementById("list");
        var lis = list.children;
        // 给 ul 添加点击事件
        list.onclick = function (e) {
            // 在内部要想办法找到真正触发事件的 li
            // 借用事件函数内部的一个参数 e,e 是事件对象
            // 只要触发事件,函数内部都可以得到一个事件对象,对象中存储了关于事件的一系列数据
            // e.target 属性记录的就是真正触发事件的事件源
            // 排除其他
            for (var i = 0 ; i < lis.length ; i++) {
                lis[i].style.backgroundColor = "";
            }
            e.target.style.backgroundColor = "pink";
        };
    </script>
</body>

</html>

请添加图片描述

事件对象

• 只要触发事件,就会有一个对象,内部存储了与事件相关的数据。
• e 在低版本浏览器中有兼容问题,低版本浏览器使用的是 window.event
• 事件对象常用的属性:
e.eventPhase 查看事件触发时所处的阶段
e.target 用于获取触发事件的元素
e.srcElement 用于获取触发事件的元素,低版本浏览器使用
e.currentTarget 用于获取绑定事件的事件源元素
e.type 获取事件类型
e.clientX/e.clientY 所有浏览器都支持,鼠标距离浏览器窗口左上角的距离
e.pageX/e.pageY IE8 以前不支持,鼠标距离整个HTML页面左上顶点的距离

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

案例

• 图片跟随鼠标移动效果

在这里插入图片描述
请添加图片描述

取消默认行为和阻止事件传播的方式

• e.preventDefault() 取消默认行为
• e.returnValue 取消默认行为,低版本浏览器使用
• e.stopPropagation(); 阻止冒泡,标准方式
• e.cancelBubble = true; 阻止冒泡,IE 低版本,标准中已废弃
在这里插入图片描述
阻止冒泡

其他事件类型

• MDN web 事件参考:https://developer.mozilla.org/zh-CN/docs/Web/Events

DOM 特效

DOM 提供了一套与元素自身有关的位置
和大小的属性。

偏移量属性

• offsetParent 偏移参考父级,距离自己最近的有定位的父级,如果都没有定位参考body(html)
• offsetLeft/offsetTop 偏移位置
• offsetWidth/offsetHeight 偏移大小
在这里插入图片描述
在这里插入图片描述

客户端大小

• client 系列没有参考父级元素。
• clientLeft/clientTop 边框区域尺寸,不常用
• clientWidth/clientHeight 边框内部大小

在这里插入图片描述

滚动偏移属性

• scrollLeft/scrollTop 盒子内部滚动出去的尺寸
• scrollWidth/scrollHeight 盒子内容的宽度和高度

在这里插入图片描述在这里插入图片描述

案例

• 拖拽案例
<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .nav {
            height: 30px;
            background: #036663;
            border-bottom: 1px solid #369;
            line-height: 30px;
            padding-left: 30px;
        }
        
        .nav a {
            color: #fff;
            text-align: center;
            font-size: 14px;
            text-decoration: none;
        }
        
        .d-box {
            width: 400px;
            height: 300px;
            border: 5px solid #eee;
            box-shadow: 2px 2px 2px 2px #666;
            position: absolute;
            top: 40%;
            left: 40%;
            background-color: white;
            /* 不让文字被选中 */
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }
        
        .hd {
            width: 100%;
            height: 25px;
            background-color: #7c9299;
            border-bottom: 1px solid #369;
            line-height: 25px;
            color: white;
            cursor: move;
        }
        
        #box_close {
            float: right;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div class="nav">
        <a href="javascript:;" id="register">注册信息</a>
    </div>
    <div class="d-box" id="d_box">
        <div class="hd" id="drop">注册信息 (可以拖拽)
            <span id="box_close">【关闭】</span>
        </div>
        <div class="bd"></div>
    </div>
    <script src="common.js"></script>
    <script>
        // 获取元素
        var box = document.getElementById("d_box");
        var drop = document.getElementById("drop");
        var close = document.getElementById("box_close");

        // 给 drop 添加鼠标按下事件,在内部继续绑定一个鼠标移动事件
        drop.onmousedown = function(e) {
            e = e || window.event;
            // 记忆鼠标按下时,鼠标在父盒子内部的间距
            var l = e.pageX - box.offsetLeft;
            var t = e.pageY - box.offsetTop;
            // 鼠标移动事件
            drop.onmousemove = function(e) {
                e = e || window.event;
                // 鼠标移动过程中,可以计算 box 的 left 和 top
                var nowleft = e.pageX - l;
                var nowtop = e.pageY - t;
                // 赋值给 box 的样式属性
                box.style.left = nowleft + "px";
                box.style.top = nowtop + "px";
            };
        };

        // 鼠标弹起事件
        drop.onmouseup = function() {
            drop.onmousemove = null;
        };

        // 点击 关闭 box
        close.onclick = function() {
            box.style.display = "none";
        };
    </script>
</body>

</html>

请添加图片描述

• 弹出登录窗
<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
        .login-header {
            width: 100%;
            text-align: center;
            height: 30px;
            font-size: 24px;
            line-height: 30px;
        }

        ul,
        li,
        ol,
        dl,
        dt,
        dd,
        div,
        p,
        span,
        h1,
        h2,
        h3,
        h4,
        h5,
        h6,
        a {
            padding: 0px;
            margin: 0px;
        }

        .login {
            width: 512px;
            position: absolute;
            border: #ebebeb solid 1px;
            height: 280px;
            left: 50%;
            right: 50%;
            background: #ffffff;
            box-shadow: 0px 0px 20px #ddd;
            z-index: 9999;
            margin-left: -256px;
            margin-top: 140px;
            display: none;
        }

        .login-title {
            width: 100%;
            margin: 10px 0px 0px 0px;
            text-align: center;
            line-height: 40px;
            height: 40px;
            font-size: 18px;
            position: relative;
            cursor: move;
            -moz-user-select: none;
            /*火狐*/
            -webkit-user-select: none;
            /*webkit浏览器*/
            -ms-user-select: none;
            /*IE10*/
            -khtml-user-select: none;
            /*早期浏览器*/
            user-select: none;
        }

        .login-input-content {
            margin-top: 20px;
        }

        .login-button {
            width: 50%;
            margin: 30px auto 0px auto;
            line-height: 40px;
            font-size: 14px;
            border: #ebebeb 1px solid;
            text-align: center;
        }

        .login-bg {
            width: 100%;
            height: 100%;
            position: fixed;
            top: 0px;
            left: 0px;
            background: #000000;
            filter: alpha(opacity=30);
            -moz-opacity: 0.3;
            -khtml-opacity: 0.3;
            opacity: 0.3;
            display: none;
        }

        a {
            text-decoration: none;
            color: #000000;
        }

        .login-button a {
            display: block;
        }

        .login-input input.list-input {
            float: left;
            line-height: 35px;
            height: 35px;
            width: 350px;
            border: #ebebeb 1px solid;
            text-indent: 5px;
        }

        .login-input {
            overflow: hidden;
            margin: 0px 0px 20px 0px;
        }

        .login-input label {
            float: left;
            width: 90px;
            padding-right: 10px;
            text-align: right;
            line-height: 35px;
            height: 35px;
            font-size: 14px;
        }

        .login-title span {
            position: absolute;
            font-size: 12px;
            right: -20px;
            top: -30px;
            background: #ffffff;
            border: #ebebeb solid 1px;
            width: 40px;
            height: 40px;
            border-radius: 20px;
        }
    </style>
</head>

<body>
    <div class="login-header"><a id="link" href="javascript:void(0);">点击,弹出登录框</a></div>
    <div id="login" class="login">
        <div id="title" class="login-title">登录会员
            <span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
        </div>
        <div class="login-input-content">
            <div class="login-input">
                <label>用户名:</label>
                <input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
            </div>
            <div class="login-input">
                <label>登录密码:</label>
                <input type="password" placeholder="请输入登录密码" name="info[password]" id="password" class="list-input">
            </div>
        </div>
        <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登录会员</a></div>
    </div>
    <!-- 遮盖层 -->
    <div id="bg" class="login-bg"></div>
    <script>
        // 获取元素
        var link = document.getElementById("link");
        var login = document.getElementById("login");
        var bg = document.getElementById("bg");
        var closeBtn = document.getElementById("closeBtn");

        // 添加 link 的点击事件,让登录窗口和遮盖层显示
        link.onclick = function () {
            login.style.display = "block";
            bg.style.display = "block";
        };

        // 添加 btn 的点击事件,让登录窗口和遮盖层隐藏
        closeBtn.onclick = function () {
            login.style.display = "none";
            bg.style.display = "none";
        };
    </script>
</body>

</html>

请添加图片描述

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值