黑马程序员JavaScript核心教程,前端基础教程,JS必会的DOM BOM操作

1.Web APIs简历导读

目标

  • 能够说出 Web APIs 阶段与JavaScript 语法阶段的关联性
  • 能够说出什么是API
  • 能够说出什么是Web API

Web APIs 和 JS 基础关联性

JS 的组成:ECMAScript(JavaScript基础)、DOM(页面文档对象模型)、BOM(浏览器对象模型)

Web APIs 包括DOM和BOM

JS 基础阶段

  • 我们学习的是 ECMAScript 标准规定的基本语法
  • 要求掌握 JS 基础语法
  • 只学习基本语法,做不了常用的网页交互效果
  • 目的是为了 JS 后面的课程打基础、做铺垫

Web APIs 阶段

  • web APIs 是w3c 组织的标准
  • web APIs 我们只要学习 DOM 和 BOM
  • web APIs 是我们 JS 独有的部分
  • 我们只要学习页面交互功能
  • 需要使用 JS 基础的课程内容做基础

JS 基础学习 ECMAScript 基础语法为后面作铺垫,web APIs 是 JS 的应用,大量使用 JS 基础语法做交互效果。

API 和 Web API

API

API (应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得意访问一组历程的能力,而又无需访问源码,或理解内部工作机制的细节。

简单理解:API 是给程序员提供一种格局,以便能更轻松的实现想要完成的功能

Web API

是浏览器提供的一套浏览器功能和页面元素的 API (BOM 和 DOM)

现阶段我们主要弹出针对浏览器讲解常用的API ,主要针对浏览器做交互效果。

比如我们想要浏览器弹出一个警示框,直接使用 alert(‘ 弹出 ‘);

MDN 详细API:developer.mozilla.org/zh-CN/docs/…

因为 Web API 很多,所以我们将这个阶段称为 Web APIs

总结

  • API 是为我们程序员提供的一个接口,帮助我们实现某种功能。
  • Web API 主要是针对于浏览器提供的接口,主要针对于浏览器做交互效果。
  • Web API 一般都有输入和输出(函数的传参和返回值),Web API 很多都是方法(函数)。
  • 学习 Web API 可以结合前面学习内置对象方法的思路学习。

2.DOM

目标

  • 能够说出什么是DOM
  • 能够获取页面元素
  • 能够给元素注册事件
  • 能够操作DOM元素的属性
  • 能够创建元素
  • 能够操作DOM 节点

DOM简介

文档对象模型,是W3C 组织推荐的处理可扩展标记语言(HTML 或者 XML)的标准编程接口。

W3C 已经得以了一系列的 DOM 接口,通过这些DOM 接口可以改变网页的内容、结构和样式。

  • 文档:一个页面就是一个文档,DOM 中使用 document 表示。
  • 元素:页面中的所有标签都是元素,DOM 中使用 element 表示。
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示。

DOM 把以上内容都看做是对象。

获取元素

如何获取页面元素

DOM 在我们实际开发中主要用来操作元素

获取页面中的元素可以使用以下几种方式:

  • 根据ID 获取
  • 根据标签名获取
  • 通过 HTML5 新增的方法获取
  • 特殊元素获取
(1)根据ID 获取

使用 getElementById() 方法获取带有 ID 的元素对象。

<body>
    <div id="time">2021-9-5</div>
    <script>
        var timer = document.getElementById('time');
        console.log(timer);         // 打印 <div id="time">2021-9-5</div>
        //console.dir 可以打印返回的元素对象,更好的查看里面的属性和方法
        console.dir(timer);
    </script>
</body>
复制代码
(2)根据标签名获取

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

<body>
    <ul>
        <li>四级词汇1</li>
        <li>四级词汇2</li>
        <li>四级词汇3</li>
        <li>四级词汇4</li>
        <li>四级词汇5</li>
    </ul>
    <script>
        // 返回的是 获取过来元素对象的集合,以伪数组的形式存储的
        var lists = document.getElementsByTagName('li');
        console.log(lists);
        console.log(lists[0]);
        // 可以通过遍历,依次打印里面的元素
        for(var i = 0; i < lists.length; i++){
            console.log(lists[i]);
        }
​
        // 如果页面中只有一个 li,返回的还是伪数组的形式
        // 如果页面中没有这个元素返回的空的伪数组的形式
​
        var ul = document.getElementsByTagName('ul');
        console.log(ul[0].getElementsByTagName('li'));
    </script>
</body>
复制代码

还可以获取某个元素(父元素)内部所有指定标签名的子元素

注意:父元素必须是 单个对象(必须指明是哪一个元素对象) ,获取的时候不包括父元素自己。

(3)HTML5 新增的方法获取
document.getElementsByClassName('类名');           // 根据类名返回元素对象集合
复制代码
document.querySelector('选择器');                  // 根据指定选择器返回第一个元素对象
复制代码
document.querySelectorAll('选择器');               // 返回指定选择器的所有元素对象集合
复制代码

实例

<body>
    <div class="box">盒子1</div>
    <div class="box">盒子2</div>
    <div id="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>
    <script>
        // 1. getElemetnsByClassName 根据类名获得某些元素集合
        var boxs = document.getElementsByClassName('box');
        console.log(boxs);
        
        // 2. querySelector 返回指定选择器的第一个元素对象
        var firstBox = document.querySelector('.box');      //类选择器
        console.log(firstBox);
        var nav = document.querySelector('#nav');
        console.log(nav);
        var li = document.querySelector('li');
        console.log(li);
​
        //3. querySelectorAll() 返回指定选择器的所有元素对象集合
        var allBox = document.querySelectorAll('.box');
        console.log(allBox);
    </script>
</body>
复制代码
(4)特殊元素获取

1、获取body 元素

2、获取html 元素

<script>
        // 1. 获取body 元素
        var bodyEle = document.body;
        console.log(bodyEle);
        console.dir(bodyEle);
​
        var htmlEle = document.documentElement;
        console.log(htmlEle);
</script>
复制代码

事件基础

事件概念

JavaScript 使我们有哪里创建动态页面,而事件是可以被JavaScript 侦测到的行为。

简单理解:触发———响应机制

网页中的每个元素都可以产生某些触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。

<body>
    <button id="btn">唐伯虎</button>
    <script>
        // 点击一个按钮,弹出对话框
        // 1. 事件是由三部分组成:事件源、事件类型、事件处理程序,称为事件三要素
        // (1) 事件源:事件被触发的对象
        var btn = document.getElementById('btn');
​
        // (2) 事件类型,如何触发,什么事件。比如鼠标点击(onclick)还是鼠标经过还是键盘按下
        // (3) 事件处理程序,通过一个函数赋值的方式,完成
        btn.onclick = function() {
            alert('点秋香');
        }
    </script>
</body>
复制代码

执行事件过程

1、获取事件源

2、注册事件(绑定事件)

3、添加事件处理程序(采用函数赋值形式)

<body>
    <div>123</div>
    <script>
        // 1. 获取事件源
        var div = document.querySelector('div');
        // 2. 绑定事件,注册时间
        //div.onclick
        // 3. 添加事件处理程序
        div.onclick = function() {
            console.log('我被选中了');
        }
    </script>
</body>
复制代码

操作元素

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

改变元素内容

(1)从起始位置到终止位置的内容,但它去除html 标签,同时空格和换行也会去掉。不识别HTML标签

element.innerText
复制代码

(2)起始位置到终止位置的全部内容,包括 html 标签,同时保留空格和换行

element.innerHTML
复制代码

实例一

<body>
    <button>显示当前系统事件</button>
    <div>某个时间</div>
    <p>123</p>
    <script>
        // 当我们点击了按钮,div 里面的文字会发生变化
        // 1. 获取元素
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        // 2. 注册事件
        btn.onclick = function() {
            //div.innerText = '2021-09-06';
            div.innerText = getDate();
        }
        function getDate() {
            var date = new Date();
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var dates = date.getDate();
            return year + '-' + month + '-' + dates;
        }
​
        // 我们元素可以不用添加事件,直接使用元素
        var p = document.querySelector('p');
        p.innerText = getDate();
    </script>
</body>
复制代码

innerText 与 innerHTML 区别

  • innerText 不识别 html 标签,非标准,去除空格和换行。
  • innerHTML 识别 html 标签,是W3C 标准,保留空格和换行。

这两个属性都是可读写的,可以获取元素里面的内容,推荐使用 innerHTML

常用元素的属性操作

1、innerText、innerHTML 改变元素内容

2、src、href

3、id、alt、title

案例:点击按钮切换图片

<body>
    <button id="anni">安妮</button>
    <button id="anna">安娜</button></br>
    <img src = "https://juejin.cn/post/安妮.jpg"  title="安妮">
​
    <script>
        // 修改元素属性  src
        // 1. 获取元素
         var anni = document.getElementById('anni');
         var anna = document.getElementById('anna');
         var img = document.querySelector('img');
        // 2. 注册事件,处理程序
        anna.onclick = function() {
            img.src = 'https://juejin.cn/post/安娜.jpg';
            img.title = '安娜';
        }
        anni.onclick = function() {
            img.src = 'https://juejin.cn/post/安妮.jpg';
            img.title = '安妮';
        }
    </script>
</body>
复制代码

修改表单属性

利用 DOM 可以操作如下表单元素的属性:

type、value、checked、selected、disabled
复制代码

案例:修改表单的值

<body>
    <button>按钮</button>
    <input type="text" value="输入内容">
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var input = document.querySelector('input');
        // 2. 注册事件,处理程序
        // 表单里面的值,文字内容是通过value 来修改的
        btn.onclick = function() {
            input.value = '点击了';
            // 如果需要某个表单被禁用,不能再点击,使用 disabled,我们想要按钮button禁用
            //btn.disabled = true;              
            // this 指向的是事件函数的调用者,在这里是 btn
            this.disabled = true;               
​
        }
    </script>
</body>
复制代码

仿京东登录页面案例

核心思路:

点击眼睛按钮,把密码框类型改为文本框就可以看见里面的密码。

一个按钮有两个状态,点击一次,切换为文本框,继续点击一次切换为密码框。

算法:利用一个flag 变量,来判断 flag 的值,如果是 1就切换为文本框,flag 设置为 0,如果是0 就切换为密码框,flag 设置为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>模仿京东显示隐藏密码明文案例</title>
    <style>
        .box {
            position: relative;
            width: 400px;
            border-bottom: 1px solid #ccc;
            margin: 100px auto;
        }
​
        .box input {
            width: 370px;
            height: 30px;
            border: 0;
            outline: none;
        }
​
        .box img {
            position: absolute;
            top: 5px;
            right: 2px;
            width: 24px;
        }
    </style>
</head>
<body>
    <div class="box">
        <label for="">
            <img src="https://juejin.cn/post/安妮.jpg"  id="eye">
        </label>
        <input type="password" name="" id="pwd">
    </div>
    <script>
        // 1. 获取元素
        var eye = document.getElementById('eye');
        var pwd = document.getElementById('pwd');
        // 2. 注册事件,处理程序
        var flag = 0;
        eye.onclick = function() {
            //点击一次之后,flag 一定要变化
            if(flag == 0){
                pwd.type = 'text';
                eye.src = 'https://juejin.cn/post/安娜.jpg';
                flag = 1;
            }else {
                pwd.type = 'password';
                eye.src = 'https://juejin.cn/post/安妮.jpg';
                flag = 0;
            }
            
        }
    </script>
</body>
</html>
复制代码

样式属性操作

我们可以通过 JS 修改元素的大小、颜色、位置等样式

1、element.style             // 行内样式操作
2、element.className         // 类名样式操作
复制代码

注意:

  • JS 里面的样式采取驼峰命名法,比如 fontSize、backgroundColor
  • JS 修改 style 样式操作,产生的是行内样式,css 权重比较高
  • 1、如果样式修改较多,可以采取操作类名方式更改元素样式。
  • 2、class 因为是个保留字,因此使用 className 来操作元素类名属性。
  • 3、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>修改div颜色和宽度</title>
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        // 1. 获取元素
        var div = document.querySelector('div');
        // 2. 注册事件,处理程序
        div.onclick = function() {
            // div.style 里面的属性,采用驼峰命名法
            this.style.backgroundColor = 'purple';
            this.style.width = '250px';
        }
    </script>
</body>
</html>
复制代码

淘宝点击关闭二维码案例

要求:当鼠标点击二维码关闭按钮的时候,则关闭整个二维码

核心思路:利用样式的显示和隐藏完成,display:none 隐藏元素,display:block 显示元素

点击按钮,就让这个二维码盒子隐藏起来即可。

<body>
    <div class="box">
        淘宝二维码<br/>
        <img src="https://juejin.cn/post/安妮.jpg" >
        <i class="close-btn">×</i>
    </div>
    <script>
        // 1. 获取元素
        var btn = document.querySelector('.close-btn');
        var box = document.querySelector('.box');
        // 2. 注册事件,程序处理
        btn.onclick = function() {
            box.style.display = 'none';
        }
    </script>
</body>
复制代码

显示隐藏文本框内容案例

要求:当鼠标点击文本框时,里面的默认文字隐藏,当鼠标离开文本框时,里面的文字显示。

案例分析

首先表单需要2个新事件,获得焦点 onfocus 失去焦点 onblur。

如果获得焦点,判断表单里面内容是否为默认文字,如果是默认文字,就清空表单内容。

<body>
    <input type="text" value="手机">
    <script>
        // 1. 获取元素
        var text = document.querySelector('input');
        // 2. 注册事件,获得焦点事件 onfocus
        text.onfocus = function() {
            if(this.value == '手机'){
                text.value = '';
            }
            console.log('得到了焦点');
        }
        // 3. 注册事件,失去焦点事件 onblur
        text.onblur = function() {
            if(this.value == ''){
                this.value = '手机';
            }
            console.log('失去了焦点');
        }
    </script>
</body>
复制代码

使用 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>Document</title>
    <style>
        .change {
            background-color: purple;
            color: #fff;
            font-size: 25px;
            margin-top: 100px;
        }
    </style>
</head>
<body>
    <div class = "first">文本</div>
    <script>
        // 1. 使用 element.style 获得修改元素样式
        // 如果样式少,或者功能简单的情况下使用
        var test = document.querySelector('div');
        test.onclick = function() {
            // 让我们的当前元素的类名改为了 change
            // 2. 我们可以通过修改元素的 className 更改元素的样式,适合与样式较多或者功能赋值的情况
            this.className = 'change';
​
            // 3. 如果想要保留原先的类名,我们可以这样做,用空格隔开(多类名选择器)
            //this.className = 'first change';
        }
    </script>
</body>
</html>
复制代码

密码框验证信息案例

如果用户离开密码框,里面输入个数不是6~16,则提示错误信息,否则提示输入正确信息。

案例分析:

  • 首先判断事件是表单失去焦点 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>Document</title>
    <style>
        div {
            width: 600px;
            margin: 100px auto;
        }
​
        .message {
            display: inline-block;
            font-size: 12px;
            color: #999;
            background: url(images/mess.png) no-repeat left center;
            padding-left: 20px;
        }
​
        .wrong {
            color: red;
            background-image: url(images/wrong.png);
        }
​
        .right {
            color: green;
            background-image: url(images/right.png);
        }
    </style>
</head>
<body>
    <div class="register">
        <input type="password" class="ipt">
        <p class="message">请输入1~16位密码</p>
    </div>
    <script>
        // 1. 获取元素
        var ipt = document.querySelector('.ipt');
        var message = document.querySelector('.message');
        // 2. 注册事件,失去焦点
        ipt.onblur = function(){
            // 根据表单里面值的长度,ipt.value.length
            if(this.value.length < 6 || this.value.length > 16){
                // console.log('错误')
                message.className = 'message wrong';
                message.innerHTML = '您输入的位数不对,要求6~16位';
            }else {
                message.className = 'message right';
                message.innerHTML = '您输入的正确';
            }
        }
    </script>
</body>
</html>
复制代码

小结

操作元素是DOM 核心内容

  • 操作元素内容:innerText、innerHTML
  • 操作常见元素属性:src、href、title、alt等
  • 操作表单属性:type、value、disabled等
  • 操作元素样式属性:element.style 、className

排他思想

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

1、所有元素全部清除样式

2、给当前元素设置样式

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

案例:多个按钮,点击按钮,按钮变粉色

<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>
    <script>
        // 1. 获取所有按钮元素
        var btns = document.getElementsByTagName('button');
        // btns 得到的是伪数组,里面的每一个元素 btns[i]
        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. 然后再让当前1的元素背景颜色为pink
                this.style.backgroundColor = 'pink';
            }
        }
    </script>
</body>
复制代码

百度换肤效果

案例:点击图片,更换背景图片

<!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;
        }
​
        body {
            background: url(images/1.jpg) no-repeat center top;
        }
​
        li {
            list-style: none;
        }
​
        .baidu {
            overflow: hidden;
            margin: 100px auto;
            background-color: #fff;
            width: 410px;
            padding-top: 3px;
        }
​
        .baidu li {
            float: left;
            margin: 0 1px;
            cursor: pointer;
        }
​
        .baidu img {
            width: 100px;
        }
    </style>
</head>
<body>
    <ul class="baidu">
        <li><img src="https://juejin.cn/post/images/1.jpg"></li>
        <li><img src="https://juejin.cn/post/images/2.jpg"></li>
        <li><img src="https://juejin.cn/post/images/3.jpg"></li>
        <li><img src="https://juejin.cn/post/images/4.jpg"></li>
    </ul>
    <script>
        // 1. 获取元素
        var imgs = document.querySelector('.baidu').querySelectorAll('img');
        // 2. 循环注册事件
        for (var i = 0; i < imgs.length; i++){
            imgs[i].onclick = function() {
                document.body.style.backgroundImage = 'url(' + this.src + ')';
            }
        }
    </script>
</body>
</html>
复制代码

表格隔行变色效果

案例分析:

用到新的鼠标事件经过 onmouseover ,鼠标离开 onmouseout。

核心思路:鼠标结果 tr 行,当前的行变悲剧颜色,鼠标离开去掉当前的背景颜色。

注意:第一行(thead 里面的行)不需要变换颜色,因此我们获取的是 tbody 里面的行。

实例:

<script>
        // 1. 获取元素 获取的是 tbody 里面所有的行
        var trs = document.querySelector('tbody').querySelectorAll('tr');
        // 2. 利用循环绑定注册事件
        for(var i = 0; i < trs.length; i++){
            // 3. 鼠标经过的事件
            trs[i].onmouseover = function() {
                //console.log('鼠标经过');
                this.className = 'bg';
            }
            // 4. 鼠标离开事件
            trs[i].onmouseout = function() {
                this.className = '';
            }
        }
</script>
复制代码

表单全选取消全选案例

案例分析:

1、全选和取消全选做法:让下面所有复选框的 checked 属性(选中状态)都跟随 全选按钮即可。

2、下面复选框需要全部选中,上面全选才能选中做法:给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的,上面全选就不选中。

<script>
        // 1. 全选和取消全选做法:让下面所有复选框的 checked 属性(选中状态)都跟随 全选按钮即可。
        // 获取元素
        var j_cbAll = document.getElementById('j_cbAll');       // 全选按钮
        var j_tbs = document.getElementById('j_tb').getElementsByTagName('input');
        // 注册事件,全选和取消全选做法
        j_cbAll.onclick = function() {
            // this.checked 可以得到当前复选框的选中状态,如果是true 就是选中,如果是false 就是未选中
            console.log(this.checked);
            for(var i = 0; i < j_tbs.length; i++){
                j_tbs[i].checked = this.checked;
            }
        }
​
        // 给下面每个复选框注册事件,下面复选框需要全部选中,上面全选才能选中
        for( var i = 0; i < j_tbs.length; i++){
            j_tbs[i].onclick = function() {
                // 每次点击下面的复选框,都要循环检查4个小按钮是否全被选中
                var flag = true;            // 控制全选按钮是否选中
                for(var j = 0; j < j_tbs.length; j++){
                    if(!j_tbs[j].checked){
                        flag = false;
                        break;
                    }
                }
                j_cbAll.checked = flag;
            }
        }
</script>
复制代码

自定义属性的操作

1.获取属性值

  • element.属性:获取属性值
  • element.getAtribute(‘属性’);//兼容性比较好

区别:

  • element.属性:获取内置属性值(元素本身自带的属性)
  • element.getAttribute(‘属性’);主要获得自定义属性(标准),我们程序员自定义的属性

实例

<body>
    <div id="demo" index="1" jack="make"></div>
    <script>
        var div = document.querySelector('div');
        // 1. 获取元素的属性
        // (1) element.属性
        console.log(div.id);
        // (2) element.getAttribute('属性'),get得到获取 attribute 属性的意思
        // 我们程序员自己添加的属性,我们称为自定义属性 index
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));
        console.log(div.getAttribute('jack'));      //自定义属性
    </script>
</body>
复制代码

2.设置移除自定义属性

(1)设置元素属性值

element.setAttribute()
复制代码

在上面的基础上添加

        // 2. 设置元素属性值
        // (1)element.属性 = '值'
        div.id = 'test';
        div.className = 'navs';
        // (2)element.setAttribute('属性', '值');主要针对于自定义属性
        div.setAttribute('index', 2);
        div.setAttribute('class', 'footer');
复制代码

(2)移除属性

removeAttribute(属性)
复制代码

tab 栏切换案例

要求:当鼠标点击上面相应的选项卡(tab),下面内容跟随变化

案例分析

1、Tab 栏切换由2大的个模块

2、上面的模块选项卡,点击某个,当前这一个底色会是红色,其余不变(排他思想),修改类名的方式

3、下面的模块内容,会跟随上面的选项卡变化。所以下面模块变化写到点击事件里面。

4、规律:下面的模块显示内容和上面的选项卡一一对应,相匹配。

5、核心思路:给上面的 tab_list 里面的所有小 li 添加自定义属性(比如 index),属性值从0 开始编号。

6、当我们点击 tab_list 里面的某个小li,让 tab_con 里面对应序号的内容显示,其余隐藏(排他思想)。

<script>
        // 1.上面的模块选项卡,点击某个,当前这一个底色会是红色,其余不变(排他思想),修改类名的方式
        // 获取元素
        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++) {
            // 开始给 5 个小 li 设置索引号
            lis[i].setAttribute('index', i);
            lis[i].onclick = function() {
                // 干掉所有人,其余的 li 清除 class 这个类
                for(var i = 0; i < lis.length; i++){
                    lis[i].className = '';
                }
                // 留下我自己
                this.className = 'current';
​
                // 2. 下面的显示内容模块
                var index = this.getAttribute('index');
                console.log(index);
                // 干掉所有人,让其余的 item 这些 div 隐藏起来
                for(var i = 0; i < items.length; i++){
                    items[i].style.display = 'none';
                }
                items[index].style.display = 'block';
            }
        }
</script>
复制代码

H5 自定义属性

自定义属性目的:是为了保存并使用数据。有些数据可以保存在页面中而不用保存到数据库中。

自定义属性获取是通过 getAttribute(‘属性’)获取。

但是有些自定义属性很容易引起歧义,不容易判断是原的内置属性还是自定义属性。

H5 给我们新增了自定义属性;

(1)设置H5 自定义属性

H5 规定自定义属性 data- 开头作为属性名并且赋值。

比如:<div data-index="1"></div>
或者
div.setAttribute('data-time', 20);
复制代码

(2)获取H5 自定义属性

1. 兼容性获取 element.getAttribute('data-index');
​
// dataset 是一个集合,里面存放了所有以 data 开头的自定义属性
// 如果自定义属性里面有多个 '-' ,dataset 后面使用小驼峰命名法 
2. H5 新增 element.dataset.index 或者 element.dataset.['index'],IE 11才开始支持。
复制代码

节点操作

为什么学节点操作?

主要目的是获取元素.

1.利用DOM提供的方法获取元素

document.getElementById()
document.getElementByTagname()
document.querySelector()
复制代码

缺点:逻辑性不强、烦琐。

2.利用节点层次关系获取元素

  • 利用父子兄节点关系获取元素
  • 逻辑性强,使用更简单,但是兼容性稍差

节点概述

网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。

HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML元素(节点)均可被修改,也可以创建或删除。

一般情况下,节点至少拥有 nodeType (节点类型)、nodeName(节点名称)和 nodeValue(节点值)这三个基本属性。

  • 元素节点 nodeType 为1
  • 属性节点 nodeType 为2
  • 文本节点 nodeType 为 3(文本节点包含文字、空格、换行等)

在实际开发中,节点操作主要操作的是元素节点

节点层次

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

父节点

得到的是离元素最近的父级节点,如果找不到父节点,就返回 null

<div class="demo">
        <div class="box">
            <span class="erweima">×</span>
        </div>
    </div>
    <script>
        // 1. 父节点 parentNode
        var erweima = document.querySelector('.erweima');
        // 得到的是离元素最近的父级节点,如果找不到父节点,就返回 null
        console.log(erweima.parentNode);
    </script>
复制代码
子节点

(标准)

parentNode.childNodes(标准)
复制代码

parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。

  • 注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。
  • 如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用 childNodes。
<ol>
        <li>我是 li 1</li>
        <li>我是 li 2</li>
        <li>我是 li 3</li>
        <li>我是 li 4</li>
</ol>
<script>
        var ul = document.querySelector('ul');
        // 1. 子节点,childNodes 所有的子节点包含元素节点,文本节点等等
        console.log(ul.childNodes);
        console.log(ul.childNodes[0].nodeType);     // 可以查看类型
        // 2. firstElementChild 返回第一个子元素节点
        console.log(ol.firstElementChild);
        console.log(ol.lastElementChild);
        // 3. 实际开发的写法,即没有兼容性问题,又返回第一个子元素,用索引下标
        console.log(ol.children[0]);
        console.log(ol.children[ol.children.length-1]);
    </script>
复制代码

(2)非标准

parentNode.children(非标准)
复制代码

parentNode.children 是一个只读属性,返回所有1子元素节点(元素节点)。它只返回子源节点,其余节点不返回(重点掌握)

虽然children 是一个非标准,但是达到了各个浏览器的支持,因此我们可以放心使用。

第一个和最后一个子元素

1、firstChile、lastChild

parentNode.firstChild
复制代码

firstChild 返回 第一个 子节点,找不到则返回 null。同样,也是 包含所有1的节点

parseNode.lastChild
复制代码

2、firstElementChild、lastElementChild

// firstElementChild 返回第一个子元素节点,找不到则返回 null
parentNode.firstElementChild
// lastElementChild 返回最后一个子元素节点,找不到则返回 null
parentNode.lastElementChild
复制代码

注意:这两个方法有兼容性问题,IE 9以上才支持。

实际开发中 ,firstChild 和 lastChild包含其他节点,操作不方便,而firstElementChild 和 lastElementChild又有兼容性问题,那么我们如何获取第一个 子元素和最后一个子元素节点呢?

        // 3. 实际开发的写法,即没有兼容性问题,又返回第一个子元素,用索引下标
        console.log(ol.children[0]);
        console.log(ol.children[ol.children.length-1]);
复制代码
新浪下拉菜单

鼠标经过,下拉菜单就出现

案例分析:

导航栏里面的 li 都要有鼠标结果效果,所以需要循环注册鼠标事件;

核心原理:当鼠标经过 li 里面的第二个孩子 ul 显示,当鼠标离开,则ul 隐藏。

<script>
        // 1. 获取元素
        var nav = document.querySelector('.nav');
        var lis = nav.children;             // 得到4个小 li
        // 2. 循环注册事件
        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>
复制代码
兄弟节点
1、node.nextSibling
复制代码

nextSibling 返回当前元素的下一个兄弟节点,找不到则返回 null 。同样,也是包含所有的节点。

2、node.previousSibling
复制代码

previousSibling 返回当前元素上一个兄弟节点,找不到则返回 null,同样,也是包含所有的节点。

3、node.nextElementSibling                       //有兼容性问题,IE9 以上才支持
复制代码

nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回 null。

4、node.previousElementSibling                   //有兼容性问题,IE9 以上才支持
复制代码

previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回 null。

如何解决兼容性问题?

答:自己反转一个兼容性的函数

//封装一个兼容性的函数
function getNextElementSibling(element) {
    var el = element;
    while (el = el.nextSibling){            // 这里是赋值操作
        if(el.nodeType === 1){
            return el;
        }
    }
     return null;
}
复制代码
创建和添加节点

(1)创建节点

document.createElement('tagName')
复制代码

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

(2)添加节点

node.appendChild(child)
复制代码

node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 css 里面的 after 伪元素。

实例

<body>
    <ul>
        <li>123</li>
        <li>456</li>
    </ul>
    <script>
        // 1. 创建节点元素节点
        var li = document.createElement('li');
        // 2. 添加节点 node.appendChild(child),node 是父级,child 是子级
        // 后面追加元素,类似于数组的 push
        var ul = document.querySelector('ul');
        ul.appendChild(li);
        // 3. 添加节点 node.insertBefore(child, 指定元素);
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[1]);
        // 4. 我们想要页面添加一个新的元素:先创建元素,再添加元素
    </script>
</body>
复制代码
简单版发布留言案例

案例分析

点击按钮之后,就动态创建一个 li,添加到 ul 里面;

创建 li 的同时,把文本域里面的值通过 li.innerHTML 赋值给 li;

如果想要新的留言后面显示就用 appendChild ,如果想要前面显示就用insertBefore

代码实现

<body>
    <textarea name="" id=""></textarea>
    <button>发布</button>
    <ul>
​
    </ul>
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var text = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        // 2. 注册事件
        btn.onclick = function() {
            if(text.value == ''){
                alert('您没有输入内容');
            }else {
                console.log(text.value);
                // (1)创建元素,并赋值
                var li = document.createElement('li');
                li.innerHTML = text.value;
                // (2)添加元素
                //ul.appendChild(li);           // 添加到后面
                ul.insertBefore(li, ul.children[0]);
            }
            
        }
    </script>
</body>
复制代码
删除节点
node.removeChild(child)
复制代码

node.removeChild( ) 方法从DOM 中删除一个子节点,返回删除的节点。

实例:

<body>
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>
    <script>
        // 1. 获取元素
        var ul = document.querySelector('ul');
        var btn = document.querySelector('button');
        // 2. 删除元素,node.removeChild(child)
        // ul.removeChild(ul.children[0]);
        // 3. 点击按钮依次删除里面的孩子
        btn.onclick = function() {
            if(ul.children.length >= 1){
                ul.removeChild(ul.children[0]);
            }
            if(ul.children.length == 0){            //如果没有节点,则按钮变灰
                this.disabled = true;
            }       
        }
    </script>
</body>
复制代码
删除留言案例

案例分析

当我们把文本域里面的值复制给 li 的时候,多添加一个删除的链接;

需要把所有的链接获取过来,当我们点击当前的链接的时候,删除当前连接所在的 li;

阻止连接跳转需要添加 javascript:void(0); 或者 javascript:;

实现:在上面 简单版发布留言案例的基础上,添加代码

<script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var text = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        // 2. 注册事件
        btn.onclick = function() {
            if(text.value == ''){
                alert('您没有输入内容');
                return false;
            }else {
                console.log(text.value);
                // (1)创建元素,并赋值
                var li = document.createElement('li');
                // javascript:; 阻止链接跳转
                li.innerHTML = text.value + '<a href="">删除</a>';
                // (2)添加元素
                //ul.appendChild(li);           // 添加到后面
                ul.insertBefore(li, ul.children[0]);
                // (3) 删除元素,删除的是当前连接的li 它的父亲
                var as = document.querySelectorAll('a');
                for(var i = 0; i < as.length; i++){
                    as[i].onclick = function() {
                        // node.removeChild(child);        //删除的是 li,当前a 所在的 li
                        ul.removeChild(this.parentNode);
                    }
                }
            }   
        }
</script>
复制代码
复制节点(克隆节点)
node.cloneNode()
复制代码

node.cloneNode() 方法返回调用该方法的节点的一个副本。也称为克隆节点/拷贝节点。

使用示例

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        // 1. node.cloneNode();  括号为空或者里面是false,浅拷贝,只复制标签不赋值里面的内容
        // 2. node.cloneNode(true); 括号为true,深拷贝,复制标签里面的内容
        var lili = ul.children[0].cloneNode(true);      //克隆 1
        ul.appendChild(lili);
    </script>
</body>
复制代码

注意:

1、如果括号参数为空或者未 false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。

2、如果括号参数为true,则是深度拷贝,会复杂节点本身以及里面的所有的子节点

\

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享