JavaScript(2)-DOM

65 阅读9分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

目录

一. 简介

二.获取元素

三.事件

四.操作元素

1.操作元素内容 

2.操作元素属性 

 五.节点

1.为什么学节点操作?

2.节点的介绍

3.节点的操作

六.案例

1.分时问候

2.仿京东显示隐藏密码明文

3.仿淘宝关闭二维码

10.TAB栏切换 223



​编辑

一. 简介

文档对象模型(Document Object Model)是处理可扩展标记语言(HTML,XML)的标准变成接口。

DOM树

​编辑

文档对象模型指的就是将这个文档中的内容都看成对象。

二.获取元素

根据ID获取

<body>
<div id="time">2022-4-11</div>
<script>
//因为文档页面从上往下加载,先得有标签,所以script写到标签的下面
var timer = document.getElementById('time');
alert(typeof timer); //object
console.log(timer);
console.dir(timer);
</script>
</body>

根据标签名获取

<body>
<div id="time" class="ti">2022-4-11</div>
<div>2022-4-12</div>
<script>
var timer = document.getElementsByTagName('div');
console.log(timer); //object
//返回的是伪数组,不支持push pop操作
</script>
</body>

document是获取页面上所有的

如何单独获取某个父标签下的子标签

<body>
<ol id="l1">
    <li></li>
    <li></li>
    <li></li>
</ol>
<script>
var elements = document.getElementsByTagName('ol');
var lis = elements[0].getElementsByTagName('li');
console.log(lis);


var l = document.getElementById('l1');
var liss = l.getElementsByTagName('li');
console.log(liss);
</script>
</body>

根据类名获取元素

var l = document.getElementsByClassName('box1');

指定选择器获取元素

querySelector        

指定选择器,可以是标签,类名或id。只返回符合条件的第一个元素

<box class="box1" id="box11">a</box>
var boxs = document.querySelector('#box11');
var boxs = document.querySelector('.box1');

querySelectorAll

指定选择器,可以获取所有符合条件的元素

var boxs = document.querySelectorAll('.box1');

特殊元素获取

获取body和html

//获取body
var b = document.body;
console.log(b);
//获取html
var h = document.documentElement;
console.log(h);

三.事件

事件基础

事件由三部分组成:事件源,事件类型,事件处理程序

事件源:触发的对象,比如按钮

事件类型:如何触发,比如鼠标点击,鼠标经过等

​编辑

事件处理程序:通过函数赋值的方式完成

<body>
<button id="btn">A</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
    alert("B");
}
</script>
</body>

给多个事件源绑定事件

<body>

<button>A</button>
<button>B</button>
<button>C</button>
<button>D</button>
<button>E</button>

<script>
var btns = document.getElementsByTagName('button');
for(var i = 0; i < btns.length; i++){
    btns[i].onclick = function (){
        //其他的按钮颜色失去
        for(var i = 0; i < btns.length; i++){
            btns[i].style.color = '';
        }
        //当前按钮颜色变色
        this.style.color = 'red';
    }
}
</script>
</body>

​编辑

​编辑

 排他思想:首先先排除其他人,再设置自己的样式2

注册事件(绑定事件)

传统注册方式

利用on开头的,如onclick

btn.onclick = function(){}  这种方式一个元素同一个事件只能设置一个处理函数,后面的会覆盖掉前面的,因为这种方式是赋值方式

方法监听注册

同一个事件可以添加多个监听器

<body>
<button>tap me</button>


<script>
var btn = document.querySelector('button');
btn.addEventListener('click',function(){
    alert('oops');
})
    /*
    * 第一个参数 type 事件类型字符串 如click,mouseover
    * 第二个参数 listener  事件处理函数,当事件发生时,会调用改监听函数
    * 第三个参数 useCapture  可选参数,是一个布尔值,默认是false
    * */
</script>
</body>

删除事件(解绑事件)

传统注册方式

btn.onclick = null           赋值为null即可

方法监听注册

<body>
<button>tap me</button>


<script>
var btn = document.querySelector('button');
btn.addEventListener('click',fn);
function fn(){
    alert('oops');
    btn.removeEventListener('click',fn);
}
</script>

传入函数的时候需要传入有名字的函数,这样后面才能解绑。

DOM事件流

 事件流描述的是从页面中接收事件的顺序。

事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。

​编辑

 给div注册事件,它的父节点们都会收到注册事件。

​编辑

 ​编辑

代码演示DOM流

演示1

点击son事件的顺序:son

<body>
<div class="father">
    <div class="son"></div>
</div>


<script>
var son = document.querySelector('.son');
//JS代码只能执行捕获或冒泡其中的一个阶段
//onclick只能得到冒泡阶段
//捕获阶段如果addEventListener第三个参数如果是true,则处于捕获阶段
son.addEventListener('click',function (){
    alert('son');
},true);
//虽然给son添加了点击事件,但是document先得到点击,但是document没有函数,所以会没有执行效果

</script>
</body>

演示2

点击son事件出现的顺序:father-son

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
.son{
    width: 100px;
    height: 100px;
    background-color: green;
}
.father{
    width: 200px;
    height: 200px;
    background-color: salmon;
}
    </style>
</head>
<body>
<div class="father">
    <div class="son"></div>
</div>


<script>
var son = document.querySelector('.son');
//JS代码只能执行捕获或冒泡其中的一个阶段
//onclick只能得到冒泡阶段
//捕获阶段如果addEventListener第三个参数如果是true,则处于捕获阶段
son.addEventListener('click',function (){
    alert('son');
},true);

var father = document.querySelector('.father');
father.addEventListener('click',function (){
    alert('father');
},true);
//虽然给son添加了点击事件,但是document先得到点击,这里给father设置了点击事件,那么点击son,father先弹出

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

如果添加事件的方法中的true改为false或不写,那么就事件流就处于冒泡阶段,先从son开始。

事件对象

var son = document.querySelector('.son');
son.onclick = function (event){
    //event是一个事件对象,当作形参来看,有了事件后,事件对象才存在,由系统自动创建,不需要我们传递参数
    //事件对象是我们事件的一系列相关数据的集合,跟事件相关的比如鼠标点击里面包含了鼠标的相关信息,鼠标坐标等
    console.log(event);
}

​编辑

var son = document.querySelector('.son');
son.addEventListener('click',function (event){ console.log(event);})

事件对象常见方法

​编辑

e.target和this区别

e.target:比如点击div触发了事件,那么就返回事件源的div

this:比如在ul中有很多li,给ul绑定事件,点击了li的话,this会返回ul而不是li,e.target会返回li,因为this指向了被绑定的元素对象。

阻止默认行为

如让链接不跳转,让提交按钮不提交。

var a = document.querySelector('a');
a.addEventListener('click',function (e){
    e.preventDefault();
})

e.returnValue;        return  false   也能阻止

阻止事件冒泡

var a = document.querySelector('a');
a.addEventListener('click',function (e){
    e.preventDefault();
    e.stopPropagation();
})

在最下面一层设置阻止冒泡,就会停止向上冒泡了

e.cancelBubble = true 也可以

事件委托

事件冒泡可以应用的地方

​编辑

事件委托的原理:不是给每个子节点单独设置事件监听器,而是事件监听器设置在父节点上,然后利用冒泡原理影响设置每个子节点。

​编辑

​编辑

<body>
<ul>
    <li>A</li>
    <li>B</li>
    <li>C</li>
    <li>D</li>
    <li>E</li>
</ul>

<script>
var ul = document.querySelector('ul');
ul.addEventListener('click',function (e){
    alert('ABCDE');
    e.target.style.backgroundColor = 'pink';//点谁谁变色
})
</script>
</body>

常见鼠标事件

​编辑

禁止鼠标右键菜单

contextmenu主要控制应该何时显示上下文菜单,主要用于取消默认上下文菜单

选中p中的文字无法右键

<body>
<p>我是一个PP</p>

<script>
var pp = document.querySelector('p');
pp.addEventListener('contextmenu',function (e){
    e.preventDefault();
})
</script>
</body>

禁止鼠标选中

<body>
<p>我是一个PP</p>

<script>
var pp = document.querySelector('p');
pp.addEventListener('selectstart',function (e){
    e.preventDefault();
})
</script>
</body>

鼠标事件对象

​编辑

常见键盘事件

​编辑

keypress区别大小写,keyup和keydown不区分大小写

键盘事件对象

​编辑

四.操作元素

1.操作元素内容

操作元素的内容        innerText    或      innerHTML

<button id="btn">A</button>

var btn = document.getElementById('btn');
btn.onclick = function (){
    btn.innerText = 'B';
}

点击按钮,将A改成B

两者的区别

1.innerText不识别HTML标签,innerHTML标签识别HTML标签

var btn = document.getElementById('btn');
btn.innerText = '<strong>C</strong>';//<strong>C</strong>
btn.innerHTML = '<strong>C</strong>';//C

2.还可以获取内容,innerText 不识别标签,innerHTML识别标签,并且保留空格和换行。

<p>
    我是p
    <span>
        我是span
    </span>
</p>

var btn = document.getElementById('btn');
console.log(btn.innerText);

<p>
    我是p
    <span>
        我是span
    </span>
</p>

var btn = document.getElementsByTagName('p');
console.log(btn[0].innerHTML);

2.操作元素属性 

操作元素的属性

<body>
<p style="font-size:50px">
    我是p
    <span>
        我是span
    </span>
</p>
<script>
var btn = document.getElementsByTagName('p');
btn[0].style = "font-size:500px";
</script>
</body>

在通过获取的元素修改样式时,比如修改color,修改后的样式等于行内样式,所以会覆盖之前的样式

操作属性style的其他属性

<body>

<p>我是P</p>

<script>
var p = document.querySelector('p');
p.style.color = 'red';
</script>
</body>

当要修改的属性多了起来,通过这种方式就会比较麻烦

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        .change{
            color:green;
        }
    </style>
</head>
<body>

<p>我是P</p>

<script>
var p = document.querySelector('p');
p.className = 'change';
</script>
</body>
</html>

使用这种方式,先设置样式,再给标签更改类属性

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style>
        .change{
            color:green;
        }
        .first{
            font-size: 50px;
        }
    </style>
</head>
<body>

<p class="first">我是P</p>

<script>
var p = document.querySelector('p');
p.className = p.className+' change';
</script>
</body>
</html>

这样还可以保留以前的类的样式,也就是一个标签设置了多个类。

获取属性的属性值

<body>

<button class="bnt1" id="btn1">A</button>
<button>B</button>
<button>C</button>
<button>D</button>
<button>E</button>

<script>
var btn = document.querySelector('.bnt1');
//方式1   element.属性
alert(btn.id);
alert(btn.className);
//方式2   element.getAttribute('属性');
alert(btn.getAttribute('class'));
</script>
</body>

两种方式的用法区别:

第一种方式只能获得内置的属性。

第二种方式还能获得自定义的属性。

这种属性是为了做区别用的,比如下面

<p index="1"></p>

设置属性值

<body>
<button class="btn1" id="btn1" index="1">A</button>

<script>
var btn = document.querySelector('.bnt1');
//方式1   element.属性
btn.className = 'btn';
//方式2   element.setAttribute('属性','值');
btn.setAttribute('index','0');
</script>
</body>

设置内置属性和自定义属性的两种方法

移除属性

btn.removeAttribute('index');

自定义属性

为了防止自定义属性和内置属性引发歧义,规定自定义属性用data-开头为属性名。

自定义属性是为了保存一些数据或者使页面某些标签做一些区分。

获取自定义属性值        getAttribute       

设置或添加自定义属性值        setAttribute

移除自定义属性            removeAttribute

五.节点

1.为什么学节点操作?

利用DOM提供的方法获取元素时,用的是document.getElementById()等等。

逻辑性不强,且繁琐

利用节点可以根据层级关系获取元素

节点的范围包括元素,元素只是标签,节点除了标签还可以是属性,属性的值,标签的内容等。

DOM树种所有节点都可以被访问。

2.节点的介绍

节点包括节点类型(nodeType),节点名称(nodeName),节点值(nodeValue)。

节点类型

元素节点nodeType为1

属性节点nodeType为2

文本节点nodeType为3(包含文字,空格,换行)

节点层级

父子兄层级关系

父级节点

var bb = btn.parentNode;//得到最近的父亲节点

子节点

var pp = btn.childNodes;//得到所有子节点,子节点包括元素节点,文本节点,空格等

var pp = btn.children;//得到所有子节点,只包括元素节点
var pp0 = btn.children[0];//得到第一个子节点

var pp = btn.firstChild;//得到第一个子节点,不管是文本节点还是元素节点
var ppp = btn.lastChild;//得到最后一个子节点,不管是文本节点还是元素节点
var pp0 = btn.firstElementChild;//返回第一个元素节点
var ppp0 = btn.lastElementChild;//返回最后一个元素节点

兄弟节点

var next = btn.nextSibling;//下一个兄弟节点,不管是元素节点还是文本节点
var previous = btn.previousSibling;//上一个兄弟节点,不管是元素节点还是文本节点
var btn2 = btn.nextElementSibling;//下一个兄弟元素节点
var btn0 = btn.previousElementSibling; //上一个兄弟元素节点

3.节点的操作

创建节点

比如添加评论的功能,添加了一个p,相当于添加了节点

只创建节点是没有效果的,还需要添加节点

添加节点

<body>
<ul id="u1">
    <li id="l1"></li>
</ul>


<script>
//创建元素    
var li = document.createElement('li');
//添加元素
var ul = document.querySelector('#ul');
ul.appendChild(li);//ul是父节点,li是子节点,将子节点放入到父节点种,追加的形式放入到父节点种
ul.insertBefore(li,ul.children[0]);//在ul第一个子节点前面插入li
</script>
</body>

删除节点

<body>
<ul id="u1">
    <li id="l1">A</li>
    <li>B</li>
    <li>C</li>
</ul>


<script>
var ul = document.querySelector('ul');
ul.removeChild(ul.children[0]);
</script>
</body>

复制节点

<body>
<ul id="u1">
    <li id="l1">A</li>
    <li>B</li>
    <li>C</li>
</ul>


<script>
var ul = document.querySelector('ul');
var clone = ul.children[0].cloneNode();//如果括号的参数为空或false,就是浅拷贝,只克隆复制节点本身,不克隆里面的节点
ul.appendChild(clone);
var clone2 = ul.children[1].cloneNode(true);//克隆节点和节点的内容
ul.appendChild(clone2);
</script>
</body>

六.案例

1.分时问候

根据时间不同,页面显示不同图片,显示不同问候语。

<body>
<img src="#" 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 ){
        div.innerText = "上午好";
    }else  if(h < 13){
        div.innerText = '中午好';
    }else if(h < 19){
        div.innerText = '下午好';
    }else {
        div.innerText = '晚上好';
    }
</script>
</body>

所用知识:

1.获取元素

2.获取时间,通过小时判断时段

3.修改元素内容,通过innerText修改标签内的内容

2.仿京东显示隐藏密码明文

注册账号时,密码输入栏中右侧按钮,单击显示密码,再点击显示*。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>

    </script>

    <style>
        .box{
            width: 400px;
            border-bottom: 1px solid #ccc;
            margin: 100px auto;
        }

        .box input{
            width: 370px;
            height: 30px;
            border: 10px;/*去掉未选中时显示的框*/
            outline: none;/*去掉选中后显示的框框*/
        }
    </style>
</head>
<body>

<div class="box">
    <input type="password" id="pwd">
    <label for="pwd">
    <img src="../images/close.webp" alt="" width="18px" height="8px" id="eye">
</label>
</div>

<script>
//获取元素
var img = document.querySelector('#eye');
var pwd = document.querySelector('#pwd');
var flag = 0;

img.onclick = function (){
    if(flag == 0){
        flag = 1;
        img.src = "../images/open.webp";
        pwd.type = 'text';
    }else{
        flag = 0;
        img.src = "../images/close.webp";
        pwd.type = 'password';
    }

}

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

​编辑

​编辑

所用知识:

1.获取元素

2.修改元素属性,通过修改input标签中的password和text属性来实现密码显示与隐藏。

3.仿淘宝关闭二维码

<body>

<div class="box">
    <img src="../images/logo.png" alt="" width="71px" height="68px">
    <i id="del">×</i>
</div>

<script>
//获取元素
var img = document.querySelector('img');
var del = document.querySelector('#del');

del.onclick = function (){
    //img.hidden = true;
    img.style.display = 'none';
}
</script>
</body>

两种隐藏方法都可以

​编辑

点击×,图片隐藏起来 

4.循环精灵图        211

5.显示隐藏文本框的内容        212

6.密码框格式提示错误信息 214

7.百度换肤        217

8.表格隔行变色        218

9.表单全选取消        219+220

10.TAB栏切换 223

11.新浪下拉菜单

碰到链接显示菜单

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-3.4.1.min.js"></script>
    <script>
        $(function () {
            var nav = document.querySelector('.nav');
            var lis = nav.children;//得到四个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>
    <style>
        a{
            text-decoration: none;
            color:black;
        }
        .nav ul{
            display: none;
            width: 100%;
        }
        .nav>li{
            float: left;
            margin: 10px;
        }

    </style>
</head>
<body>
<ul class="nav">
    <li>
        <a href="#">微博</a>
        <ul>
            <li>私信</li>
            <li>评论</li>
            <li>@我</li>
        </ul>
    </li>
    <li>
        <a href="#">微博</a>
        <ul>
            <li>私信</li>
            <li>评论</li>
            <li>@我</li>
        </ul>
    </li>
    <li>
        <a href="#">微博</a>
        <ul>
            <li>私信</li>
            <li>评论</li>
            <li>@我</li>
        </ul>
    </li>
    <li>
        <a href="#">微博</a>
        <ul>
            <li>私信</li>
            <li>评论</li>
            <li>@我</li>
        </ul>
    </li>
</ul>
</body>
</html>

​编辑

​编辑

12.发布留言 234

13.删除留言 236

14.动态生成表格 238

15.跟随鼠标的天使 267

16.模拟京东输入内容案例

\