学习js中的DOM

学习js中的DOM

一、WebApi基本概念

1.为什么要学习WebApi?

在这里插入图片描述

2.什么是WebApi

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

二、DOM-文档对象模型

1.DOM基本概念

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        
        <div id="box">
            <!-- 这是注释 -->
            这是文字
        </div>

        <script>
            // DOM基本概念: 文档对象模型
            // 文档指的即使整个网页。网页视为一个对象
            // 文档内的所有内容都当成一个个对象(文字、属性、标签、注释)

            // 对象里面提供了属性和方法,就可以方便去操作页面中的元素。


            // 常见的概念:
            //  文档: document, 整个页面
            //  节点: node, 页面中的任何内容
            //  元素: element, 标签节点


            // dom又称为文档树模型: 能够方便的去查找到该节点的父亲、兄弟、孩子是谁。


            // 小结;
            //  1. dom:  
            //      1. 文档对象模型(把网页和页面中所有的内容都当成对象)
            //      2. 文档树模型: 

            //  2. 常见概念:
            //      1. 文档
            //      2. 节点(所有内容)
            //      3. 元素
        </script>
    </body>
</html>

2.DOM初体验

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <img id="pic" src="imgs/01.jpg" alt="这是啥图片" title="今天在37期上课">

    <script>
        // DOM初体验

        // 要去操作一个元素之前,一定需要获取到该元素

        // document : 文档, 是一个对象
        // document.getElementById();
        // 作用: 在页面中,通过id去获取元素
        // 参数:字符串类型的id名称
        // 返回值:返回了获取到的元素

        var ret = document.getElementById("pic");
        // console.log(ret); // 使用该方法打印返回的元素,就是以标签的形式展示
        console.dir(ret); // 使用该方法打印返回的元素,以对象的形式可以展开查看里面的属性和方法。


        // dom对象上的属性和方法和标签上的一样的(一一对应的)
        // 所有可以通过dom对象去修改标签上的属性(dom对象上属性修改了,对应的标签上的属性也会被修改)

         // 通过dom对象去设置属性
        ret.alt = "这是个妹子";
        ret.src = "imgs/02.jpg";

        // 通过dom对象去获取属性
        // console.log(ret.alt);
        // console.log(ret.title);


        // 小结:
        //  1. document.getElementById()   通过id去获取元素
        //  2. dom对象中的属性和标签中的属性是一一对应的(只要修改了dom对象中的属性,标签中的属性就会被修改)
    </script>
</body>
</html>

3.使用getElementById的注意事项

在这里插入图片描述

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

</head>
<body>
    
    <img id="box" src="imgs/1.jpg" alt="这是图片">


    
    <script>
        // 使用getElementById的注意事项

        // 1. id 名称必须写, 不能写错
        // var ret = document.getElementById("box2");
        // console.log(ret);

        // 如果元素没有获取到,ret将是null,会error
        // ret.src = "imgs/01.jpg";


        // 2. 该js代码不要写在head标签中


        // 3. 由于id名称是页面中唯一的标识,所有有些浏览器直接通过id名称去拿到元素(不需要经过方法获取) 。 不推荐这么去获取元素,这是个不好的规范。
        console.log(box);


        // 小结:
        //  1. id名称没有或者有错误
        //  2. js代码不要放在head中
        //  3. id是可以直接拿来用的,但是不推荐这么做。
    </script>

</body>
</html>

4.事件的基本使用

在这里插入图片描述

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

    <button id="btn">按钮</button>
    <img id="pic" src="imgs/1.jpg" alt="这是第一张图片">


    <script>
        // 事件

        // 触发-响应的机制

        // 事件的三要素
        // 1. 事件源, 触发事件的元素
        // 2. 事件名,比如说点击事件
        // 3. 事件处理程序, 事件处理函数,事件触发后要做什么

        // 该案例中:
        // 事件三要素分别是:
        //  1. 事件源: 按钮
        //  2. 事件名: 点击事件   click
        //  3. 事件处理函数: 切换图片, 更换src属性值


        // 注册事件的语法:
        // on: 当...的时候    onclick 当点击的时候
        /*事件源.on事件名 = function () {
            
        }*/


        // 思路:
        // 1. 找对象(按钮、图片)
        // 2. 按钮注册上点击事件
        // 3. 点击的时候,采取更换图片的src属性值

        // 1. 
        var pic = document.getElementById("pic");
        var btn = document.getElementById("btn");

        // 2.
        // 给按钮注册了点击事件,点击了就执行后面函数,打印1
        btn.onclick = function(){
            // 这里的代码默认是不会主动执行的,只要按钮被点击了才会执行
            // alert(1);

            console.log(1);
            // 3.
            pic.src = "imgs/2.jpg";

        }


        // 小结:
        //  事件: 机制(触发-响应)
        //  事件的三要素
        //  注册事件由三要素组成
        //  注意: 事处理函数中的代码默认不执行,只有事件触发了才会执行的
    </script>
</body>
</html>

5.修改标签的属性

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <button id="btn">按钮</button>
    <img id="pic" src="imgs/1.jpg" alt="这是第一张图片" width="300">
    <script>
        // 点击按钮,修改图片的宽高

        // 1. 找对象
        // 2. 按钮注册点击事件
        // 3. 点击过后更换图片的width、height

        // 1.
        var btn = document.getElementById("btn");
        var pic = document.getElementById("pic");

        // 2.
        btn.onclick = function () {
            // 3.
            pic.width = "500";
            pic.height = "500";
        }

    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 100px;
            height: 100px;
            background-color: #f99;
        }
        .box{
            width: 300px;
            height: 300px;
            background-color: lime;
        }
    </style>
</head>
<body>

    <button id="btn">按钮</button>
    <div id="box2"></div>

    <script>
        // 修改div的样式, 给div添加box类名

        var btn = document.getElementById("btn");
        var box2 = document.getElementById("box2");

        btn.onclick = function () {

            // console.log(1);

            // class 在js中是一个关键字,有特殊的作用的,所有在标签中是class。但是在dom对象中,对应的是className属性
            // box2.class = "box";  // 错误写法

            // 注意点
            box2.className = "box";
        }


        // 小结:
        //  class属性特殊: 标签中的class属性对应了dom对象中的className属性。
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 300px;
            height: 300px;
            background-color: #f99;
            display: none;
        }
        /*展示的类名*/
        .show{
            display: block;
        }
    </style>
</head>
<body>

    <button id="btn1">显示</button>
    <button id="btn2">隐藏</button>
    
    <div id="box"></div>


    <script>
        // 点击按钮,显示与隐藏


        // 思路:
        // 1
        var btn1 = document.getElementById("btn1");
        var btn2 = document.getElementById("btn2");
        var box = document.getElementById("box");


        // 2.
        // 显示
        btn1.onclick = function () {
            box.className = "show";
        }

        // 隐藏
        btn2.onclick = function () {
            // 类名变成空字符串,就会把show类名去掉
            box.className = "";
        }



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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 300px;
            height: 300px;
            background-color: #f99;
            display: none;
        }
        /*展示的类名*/
        .show{
            display: block;
        }
    </style>
</head>
<body>

    <button id="btn" value="显示2222">显示</button>
    <div id="box"></div>

    <script>
        // 点击按钮,显示与隐藏


         // 思路:
        // 1
        var btn = document.getElementById("btn");
        var box = document.getElementById("box");


        // 修改文字内容 innerText

        // 获取按钮的文字内容
        // console.log(btn.innerText);
        // btn.innerText = "隐藏";


        // 现在如何到达切换文字的效果
        //  1. 点击按钮的时候,判断按钮的文字:
        //      1.1 为显示,修改成 隐藏
        //      1.2 为隐藏, 修改成显示

        // 实现第一个功能:点击按钮,修改按钮的文字
        btn.onclick = function () {
            // btn.innerText = "隐藏";

            // 注意点坑: if语句里面是 == ,做判断用的
            // 下面的代码, = 是赋值
            if(btn.innerText == "显示"){
                // 1.1 为显示,修改成 隐藏
                btn.innerText = "隐藏";

                box.className = "show";
            }else if(btn.innerText == "隐藏"){
                btn.innerText = "显示";

                box.className = "";
            }
        }


        // 小结:
        //  innerText  操作文本内容(获取、设置)
        //  className 属性 操作类名
    </script>
</body>
</html>

6.getElementsByTagName

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
        
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>
    <p>内容</p>

    <script>
        // getElementsByTagName  获取元素
        // 作用: 通过标签名去获取元素
        // 参数:字符串类型的标签名 "p"
        // 返回值:返回了一个伪数组, 里面就是获取到的每一个元素
        // 伪数组:是一个对象,有数字下标还有length 属性。因为可以像数组一样进行遍历,但是不能使用数组的方法


        var ret = document.getElementsByTagName("p");
        console.log(ret); // ret 是一个伪数组,所有可以for循环进行遍历


        // 设置每一个p的内容
        for(var i = 0; i < ret.length; i++){
            // 如何给每一个p设置文字内容
            // ret[i] ==> 每一个p标签

            ret[i].innerText = "设置后的内容";
        }


        // 设置某一个p的内容
        ret[0].innerText = "莲妹最漂亮";


        // 小结:
        //  1. document.getElementsByTagName();
        //  2. 返回值是一个伪数组
        //  3. 遍历伪数组就可以操作伪数组中的每一项了
        //  4. 不管有没有获取到元素,返回的都是一个伪数组
        //        而getElementById没有获取到元素返回null


        /*function fn(){
            console.log(arguments);

            arguments.push(40);
        }

        fn(10,20,30)*/


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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>

    <script>
        // 1. 找到所有的按钮  getElementsByTagName
        // 2. for循环遍历每一个按钮,每一个按钮注册 上click

        // 1.
        var btns = document.getElementsByTagName("button");

        // 2.
        for(var i = 0; i < btns.length; i++){
            btns[i].onclick = function () {
                alert(1)
            }
        }
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .red{
            background-color: red;
        }
        .pink{
            background-color: pink;
        }
    </style>
</head>
<body>
    <ul id="box">
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
        <li>莲妹去哪了</li>
    </ul>
    
    <ol>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
        <li>这是li是不需要隔行变色效果</li>
    </ol>


    <script>
        // 1. 找对象
        // 2. for循环遍历每一个li设置背景颜色

        // 1.
        // var lis = document.getElementsByTagName("li");
        // 这是在整个页面中查找li元素,获取的就是页面中所有的li元素


        // 这样能够更加精确的获取元素(范围变小)
        var ul = document.getElementById("box");
        var lis = ul.getElementsByTagName("li");

        // 元素.getElementsByTagName();
        // 作用:从某个具体的元素里面去根据标签名获取元素

        // 2.
        for(var i = 0; i < lis.length; i++){
            // 这样是所有的li都是red
            // lis[i].className = "red";

            if(i % 2 == 0){
                // i 是偶数
                // lis[i] ==> 下标为偶数的那个li
                lis[i].className = "red";
            }else{
                lis[i].className = "pink"
            }
        }


        // 小结:
        //  document.getElementsByTagName()  ==> 从整个页面中获取元素
        //  box.getElementsByTagName()  ==> 从box中获取元素
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <div id="box">
        <p>这是p内容</p>
        <div>这是div里面的div</div>
    </div>

    <script>
        // 通过id来获取元素
        // document.getElementById(id)
        // box.getElementById()  ==> 没有这种写法
        // 
        // 通过标签名去获取元素
        // 1. document.getElementsByTagName(name)
        // 2. box.getElementsByTagName(name)


        // 区别:
        //  1. 通过id来获取元素, 返回结果是获取的元素,没有获取到返回null
        //  2. 通过标签名去获取元素, 返回的结果是伪数组,没有返回的结果还是伪数组

        // 找p
        var p = document.getElementsByTagName("p")[0];
        console.log(p);

        // 找div
        // var box = document.getElementById("box");
        // var div = box.getElementsByTagName("div")[0];

        // 上面代码的简写形式
        var div = document.getElementById("box").getElementsByTagName("div")[0];

        console.log(div);
    </script>
</body>
</html>

7.事件中的this

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button>按钮</button>

    <script>
        // 需求: 点击按钮,修改按钮自身的文字

        var btn = document.getElementsByTagName("button")[0];

        btn.onclick = function () {
            btn.innerText = "今天的内容觉得难吗";

            // this , 在事件处理函数中,this指向了触发事件的当前元素。
            // console.log(this);
            this.innerText = "今天的内容觉得难吗, 不难";
        }
        
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .red{
            background-color: red;
        }
    </style>
</head>
<body>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>

    <script>
        // 1. 找对象(所有的按钮)
        // 2. 循环遍历每一个button,每一个button注册click

        // 1.
        var btns = document.getElementsByTagName("button");

        // 2.
        for (var i = 0; i < btns.length; i++) {
            // 给每一个按钮注册click
            btns[i].onclick = function(){

                console.log(i);  // 10

                // error 
                // btns ==> 伪数组, 下标的范围是0-9之间
                // 不要这么写, why? 因为在点击的时候,for循环已经结束了。i = 最后的结果为10,导致btns[i] 没有获取到元素
                // btns[i]  ==> btns[10]  ==> undefined
                // btns[i].className = "red";

                // 点谁谁变红
                // console.log(this);
                this.className = "red";
            }

            console.log(i); // 0 - 9
        }

        // 循环结束后,i的值已经变成了10 

        // 小结:
        // this ==> 
        //  1. 谁调用,this就指向谁
        //  2. 在事件中,this指向了触发事件的当前元素
    </script>
</body>
</html>

8.阻止a标签跳转

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <a id="link" href="http://qingliujushi.com">我是大聪哥</a>

    <script>
        // 阻止a标签跳转

        // 如果需要阻止a链接的跳转,就需要给a链接注册click,在事件处理函数中,return false;

        var link = document.getElementById("link");

        link.onclick = function(){
            alert(1);

            // 阻止跳转的目的
            return false;
        }
        
    </script>
</body>
</html>

9.美女相册案例

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    body {
        padding-left: 100px;
    }

    #imgs {
        overflow: hidden;
        margin: 50px 0;
    }

    #imgs li {
        float: left;
        margin-right: 10px;
    }
    </style>
</head>

<body>
    <h1>美女相册</h1>
    <ul id="imgs">
        <li>
            <a href="images/1.jpg" title="美女A">
                <img src="images/1-small.jpg" alt="">
            </a>
        </li>
        <li>
            <a href="images/2.jpg" title="美女B">
                <img src="images/2-small.jpg" alt="">
            </a>
        </li>
        <li>
            <a href="images/3.jpg" title="美女C">
                <img src="images/3-small.jpg" alt="">
            </a>
        </li>
        <li>
            <a href="images/4.jpg" title="美女D">
                <img src="images/4-small.jpg" alt="">
            </a>
        </li>
    </ul>
    <!-- 大图 -->
    <img src="images/placeholder.png" width="400" height="250" alt="" id="bigImg">

    <!--说明信息-->
    <p id="des">这是描述信息</p>

    <script>
        
        // 思路:
        //  1. 找对象 (找到所有的a)
        //  2. 给a 注册 click
        //  3. 禁止跳转
        //  4. bigImg的src 换成 当前点击的a的href属性值
        //  5. des的文字内容换成 当前点击的a的title属性值


        // 1.
        var imgs = document.getElementById("imgs"); // ul
        // 获取a的范围小,更加精确
        var as = imgs.getElementsByTagName("a");  // a
        var bigImg = document.getElementById("bigImg"); // bigImg
        var des = document.getElementById("des");  // des

        // 2.
        for (var i = 0; i < as.length; i++) {
            as[i].onclick = function () {
                // 4.
                bigImg.src = this.href;
                // 5. 
                des.innerText = this.title;
                // 3.
                return false;
            }
        }


        // 小结:
        //  1. 标签中的属性和dom对象的属性是一一对应的
        //  2. 给a注册点击事件,阻止a的跳转

    </script>
</body>

</html>

三、属性操作

1.普通标签属性

在这里插入图片描述

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
    .nodeSmall {
        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;
    }

    .nodeSmall a {
        display: block;
        width: 50px;
        height: 50px;
    }

    .hide {
        display: none;
    }

    .show {
        display: block;
    }
    </style>
</head>

<body>
    <div class="nodeSmall" id="node_small">
        <a href="#" id="link"></a>
        <div class="erweima hide" id="er">
            <img src="images/456.png" alt=""/>
        </div>
    </div>
    
    <script>
        // 思路: 
        // 1. 找对象  找a
        // 2. 给a 注册 onmouseover
        // 3. 二维码的hide类名去掉,二维码就展示出来了
        // 4. 给a注册 onmouseout
        // 5. 二维码的hide类名加上,二维码就隐藏了


        //  onclick 点击事件
        //  鼠标移入事件  onmouseover(当鼠标移入上去的时候触发)
        //  onmouseout 鼠标离开事件


        // 1.
        var link = document.getElementById("link");
        var er = document.getElementById("er");

        // 2.
        link.onmouseover = function(){
            // 3.
            // 坑: 设置类名的时候,注意一下,标签中自带的类名
            er.className = "erweima";
        }

        // 4,
        link.onmouseout = function () {
            er.className = "erweima hide";
        }   

        // 小结
        //  1. onmouseover   onmouseout
        //  2. className 在设置类名的时候,会覆盖原来的类名,所以注意细节。
    </script>
</body>

</html>

2.表单属性操作

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <button id="btn">按钮</button>

    <!-- <input type="text" name="" value="" id="inp1">
    <input type="checkbox" checked>
    <select name="" id="">
        <option value="1">1</option>
        <option value="1" selected>2</option>
    </select> -->

    <script>
        // 表单属性操作

        // 布尔类型的属性: disabled、checked、selected
        // 1. 标签中看:这些属性只要标签中有,就可以起到效果
        // 2. 从dom对象上看,这些属性在dom对象中都是布尔类型的(true/false)

        /*var inp1 = document.getElementById("inp1");
        console.log(inp1.disabled);*/


        // 禁用按钮

        var btn = document.getElementById("btn");
        btn.onclick = function () {
            // 通过dom对象去设置disabled属性,值为布尔类型。
            this.disabled = true;
        }


        // 小结:
        //  1. 常见属性: type name value 、。。。
        //  2. 布尔类型属性: 

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <input type="text" value="这是内容" id="inp">

    <script>
        
        var inp = document.getElementById("inp");
        inp.onclick = function () {
            this.disabled = true;
        }

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

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</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="checkbox"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="text"><br>
    <input type="button" id="btn" value="禁用所有的文本框">
    
    <script>
        // 禁用所有的文本框

        // 思路:
        //  1. 找对象  按钮  文本框
        //  2. 给按钮注册click
        //  3. 禁用所有的文本框

        // 1.
        var btn = document.getElementById("btn");
        var inps = document.getElementsByTagName("input");

        // 2.
        btn.onclick = function () {
            // 3.
            for(var i = 0; i < inps.length; i++){
                // 这样是所有的input都被禁用了
                // inps[i].disabled = true;

                // 进行判断,判断是否为文本框
                if(inps[i].type == "text"){
                    // 文本框
                    inps[i].disabled = true;
                }

            }
        }

        // 小结:
        //  for循环, 循环里面判断input的type 类名
        //   disabled + type 属性一起使用完成效果。
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="zh-CN">

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

<body>
    <input type="button" value="翻牌子" id="btn">

    <select>
        <option value="小马哥">小马哥</option>
        <option value="大葱哥">大葱哥</option>
        <option value="小莲妹">小莲妹</option>
        <option value="小旺旺">小旺旺</option>
        <option value="小汪汪">小汪汪</option>
        <option value="小班">小班</option>
    </select>

    <script>
        // 思路:
        //  1. 找对象  按钮  下拉框
        //  2. 给按钮注册 click
        //  3. 随机选中一个option,让其是选中效果 (selected)
                // 随机一个下标,通过下标去选出对应下标的option
                //  下标的范围: 0-options.length - 1
                //  Math.random()  ==> [0, 1) * options.length

        // 1.
        var btn = document.getElementById("btn");
        var slt = document.getElementsByTagName("select")[0];
        var options = slt.getElementsByTagName("option");

        // 2.
        btn.onclick = function(){
            // 3.
            var index = parseInt(Math.random() * options.length);

            options[index].selected = true;
        }


        // 小结:
        //  使用Math.random 生成随机小数,得到随机的下标
        //  根据下标去找到对应下标的option,设置他的selected属性值为true
        //  selected属性
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="zh-CN">

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

<body>
    <input type="text" id="txt" value="蚕丝被">
    <script>
        // 思路:
        //  1. 找对象
        //  2. 给 input 注册onfocus事件
        //      onfocus :  聚焦事件,
        //      onblur: 失焦事件
        //  3. 把文本框的value值清空
        //  4. 给 input 注册 onblur 事件
        //  5. 把文本框的value 值变成默认值


        // 1.
        var txt = document.getElementById("txt");
        // 2,
        txt.onfocus = function(){
            // 3.
            //  聚焦的时候,变成空字符串,条件是文本框的内容为默认值
            if(this.value.trim() == "蚕丝被"){
                this.value = "";
            }
        }

        // 4.
        txt.onblur = function () {
            // 5.
            // 失焦的时候,恢复成默认值,条件是文本框没有输入内容
            // trim()  ==> 去掉字符串两端的空格
            if(this.value.trim() == ""){
                this.value = "蚕丝被";
            }
        }

        // 小结:
        //  1. onfocus onblur
        //  2. value属性
    </script>
</body>

</html>

<!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;
      text-align: center;
    }

    tbody tr:hover {
      cursor: pointer;
      background-color: #fafafa;
    }
  </style>
</head>

<body>
    <div class="wrap">
        <table>
            <thead>
                <tr>
                    <th>
                        <input type="checkbox" id="j_cbAll" />
                    </th>
                    <th>菜名</th>
                    <th>饭店</th>
                </tr>
            </thead>
            <tbody id="j_tb">
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>红烧肉</td>
                    <td>田老师</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>西红柿鸡蛋</td>
                    <td>田老师</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>红烧狮子头</td>
                    <td>田老师</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>日式肥牛</td>
                    <td>田老师</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
    // 功能:
    //  1. 全选可以控制下面四个input的选中状态
    //  思路: 
    //  1.1 找对象 (全选 四个)
    //  1.2 全选注册click
    //  1.3 获取到全选的选中状态 
    //  1.4 下面四个input的选中状态同步为全选的选中状态

    // 1.1
    var all = document.getElementById("j_cbAll");
    var inps = document.getElementById("j_tb").getElementsByTagName("input");

    // 1.2
    all.onclick = function() {
        // 1.3
        var ret = this.checked;
        // 1.4
        for (var i = 0; i < inps.length; i++) {
            // 下面四个input每一个都被选中了
            inps[i].checked = ret;
        }
    }


    //  2. 下面四个input可以控制全选的选中状态
    //  思路: 
    //  2.1 给四个input注册click
    //  2.2 判断四个input是否都被选中了
    //    1. 如果四个都被选中了,全选就要被选中了
    //    2. 只有要一个input没有被选中,全选就不需要被选中

    // 2.1
    // 这里的for循环是用来给每一个input注册点击事件
    for (var i = 0; i < inps.length; i++) {
        inps[i].onclick = function() {
            // 2.2
            var flag = true; // 假设都被选中了

            // 循环遍历每一个input是否都被选中了
            for (var i = 0; i < inps.length; i++) {
                if (inps[i].checked == false) {
                    // 没有被选中
                    flag = false;
                    break;
                }
            }

            if (flag == true) {
                // 四个input都被选中了
                all.checked = true;
            } else {
                // 至少有一个input没有被选中
                all.checked = false;
            }
        }
    }


    // 小结:
    //  checked,多选框的选中状态
    //  假设成立法,就可以获取下面四个input是否都被选中了
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        var arr = [1, 3, 5, 9];

        // 得到这个数组是否都是奇数

        // 假设成立法

        // 1. 假设一种情况
        // 2. 推翻你的假设, 打脸

        var flag = true;  // 假设都是奇数

        // 循环遍历数组中的每一项是否都是奇数
        for(var i = 0; i < arr.length; i++){
            if(arr[i] % 2 == 0){
                // 偶数
                flag = false;
                break;
            }
        }

        // 得到结果
        console.log(flag);
    </script>
</body>
</html>

<!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;
      text-align: center;
    }

    tbody tr:hover {
      cursor: pointer;
      background-color: #fafafa;
    }
  </style>
</head>

<body>
    <div class="wrap">
        <table>
            <thead>
                <tr>
                    <th>
                        <input type="checkbox" id="j_cbAll" />
                    </th>
                    <th>菜名</th>
                    <th>饭店</th>
                </tr>
            </thead>
            <tbody id="j_tb">
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>红烧肉</td>
                    <td>田老师</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>西红柿鸡蛋</td>
                    <td>田老师</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>红烧狮子头</td>
                    <td>田老师</td>
                </tr>
                <tr>
                    <td>
                        <input type="checkbox" />
                    </td>
                    <td>日式肥牛</td>
                    <td>田老师</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
    // 功能:
    //  1. 全选可以控制下面四个input的选中状态
    //  思路: 
    //  1.1 找对象 (全选 四个)
    //  1.2 全选注册click
    //  1.3 获取到全选的选中状态 
    //  1.4 下面四个input的选中状态同步为全选的选中状态

    // 1.1
    var all = document.getElementById("j_cbAll");
    var inps = document.getElementById("j_tb").getElementsByTagName("input");

    // 1.2
    all.onclick = function() {
        // 1.4
        for (var i = 0; i < inps.length; i++) {
            // 下面四个input每一个都被选中了
            // 优化01
            inps[i].checked = this.checked;
        }
    }


    //  2. 下面四个input可以控制全选的选中状态
    //  思路: 
    //  2.1 给四个input注册click
    //  2.2 判断四个input是否都被选中了
    //    1. 如果四个都被选中了,全选就要被选中了
    //    2. 只有要一个input没有被选中,全选就不需要被选中

    // 2.1
    // 这里的for循环是用来给每一个input注册点击事件
    for (var i = 0; i < inps.length; i++) {
        inps[i].onclick = function() {
            // 2.2
            var flag = true; // 假设都被选中了

            // 循环遍历每一个input是否都被选中了
            for (var i = 0; i < inps.length; i++) {
                // 优化02
                if (!inps[i].checked) {
                    // 没有被选中
                    flag = false;
                    break;
                }
            }


            // 优化03
            /*if (flag) { // true
                // 四个input都被选中了
                all.checked = true;
            } else { // false
                // 至少有一个input没有被选中
                all.checked = false;
            }*/

            // 精简后的代码  flag 的布尔值就决定了全选的选中状态
            all.checked = flag;

            // 三元优化, 不够优化
            // flag ? all.checked = true : all.checked = false;

        }
    }


    // 小结:
    //  checked,多选框的选中状态
    //  假设成立法,就可以获取下面四个input是否都被选中了
    </script>
</body>

</html>

3.标签的自定义属性

在这里插入图片描述

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="box" title="这是个div" class="box" aa="bb">123</div>

    <script>
        // 标签的自定义属性
        // 自定义属性的作用: 把数据存储到自定义属性上

        // 固有属性: 标签中本来就有的属性 title。。。
        // 自定义属性: 不是固有属性

        var box = document.getElementById("box");

        // console.log(box.title);

        // 标签中的属性和dom对象的属性是一一对应的,限制于固有属性

        // 自定义属性不可以通过dom对象去获取
        // console.log(box.aa);  // undefined

        // 给box对象添加了aa属性,值为abc, dom对象上有了aa属性,但是标签中的aa属性值没有发生改变。
        // box.aa = "abc";
        // console.dir(box)


        // 属性操作方法
        // getAttribute(name);  // name 就是字符串类型的属性名
        // 作用: 获取标签上的属性值,注意: 是拿标签上的属性
        // 注意点: 属性操作方法只要是标签的属性都可以操作(不管属性是固有的,还是自定义的都可以操作)

        box.bb = "def";

        console.log(box.getAttribute("title"));
        console.log(box.getAttribute("bb"));


        // 说明了我们操作固有属性有两种方式
        //  1. dom对象去操作   box.title   方便
        //  2. 属性操作方法    box.getAttribute("title")


        // 细节地方
        // 操作类名,注意写法不同
        // console.log(box.className);  // dom对象需要通过 className才可以去获取到类名
        // console.log(box.getAttribute("class"));  // getAttribute,参数是个字符串,直接写class


        // 小结:
        //  1. 固有属性
        //  2. 自定义属性, 作用:在自定义属性上存储数据
        //  3. dom对象的属性和标签中的属性是一一对应的,仅仅限制于固有固有属性
        //      dom对象不能操作自定义属性。
        //  4. 属性操作方法  (不管是固有的、自定义的属性都可以操作)
        //      getAttribute("属性名")
        //  5. 细节:
        //          getAttribute("class")
        //          box.className
        //  6. dom对象操作固有属性有两种方式

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="box" title="这是个div" class="box" aa="bb">123</div>

    <script>
        // 标签的自定义属性
        // 自定义属性的作用: 把数据存储到自定义属性上

        // 固有属性: 标签中本来就有的属性 title。。。
        // 自定义属性: 不是固有属性

        var box = document.getElementById("box");

        // 属性操作方法
        // getAttribute(name);  // name 就是字符串类型的属性名
        // 作用: 获取标签上的属性值,注意: 是拿标签上的属性
        // 注意点: 属性操作方法只要是标签的属性都可以操作(不管属性是固有的,还是自定义的都可以操作)

        //  setAttribute(name, value)
        //  name : 字符串类型的属性名
        //  value: 属性值
        //  作用: 给标签设置属性
        box.setAttribute("bb", "def");
        console.dir(box);
        box.setAttribute("title", "我把title属性值修改了");

        // box.title = "我把title属性值修改了"


        // removeAttribute(name)
        // name : 字符串类型的属性名
        // 作用: 移除标签中的属性
        box.removeAttribute("class");
        box.removeAttribute("aa");
        box.removeAttribute("bb");




        console.log(box.getAttribute("title"));
        console.log(box.getAttribute("bb"));


        // 说明了我们操作固有属性有两种方式
        //  1. dom对象去操作   box.title   方便
        //  2. 属性操作方法    box.getAttribute("title")


        // 细节地方
        // 操作类名,注意写法不同
        // console.log(box.className);  // dom对象需要通过 className才可以去获取到类名
        // console.log(box.getAttribute("class"));  // getAttribute,参数是个字符串,直接写class


        // 小结:
        //  1. 固有属性
        //  2. 自定义属性, 作用:在自定义属性上存储数据
        //  3. dom对象的属性和标签中的属性是一一对应的,仅仅限制于固有固有属性
        //      dom对象不能操作自定义属性。
        //  4. 属性操作方法  (不管是固有的、自定义的属性都可以操作)
        //      getAttribute("属性名")
        //  5. 细节:
        //          getAttribute("class")
        //          box.className
        //  6. dom对象操作固有属性有两种方式
        //  7. 属性操作方法更多的是用在自定义属性属性上
        //  8. 属性操作方法,可以操作固有的,也可以操作自定义的属性
    </script>
</body>
</html>

4.tab栏案例

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .red{
            background-color: red;
        }
    </style>
</head>
<body>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>

    <script>
        // 排他思想
        // 1. 干掉所有人
        // 2. 复活我自己

        // 需求:每次点击的时候,只能由一个按钮变红

        // 干掉所有人 ==> 在点击的时候,先把所有的按钮的red类名去掉
        // 复活我自己 ==> 把当前点击的这个元素添加red类名


        var btns = document.getElementsByTagName("button");

        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function () {
                // 点谁给谁添加red类名
                // this.className = "red";

                // 1. 干掉所有人
                for (var i = 0; i < btns.length; i++) {
                    btns[i].className = "";
                }

                // 2. 复活我自己
                this.className = "red";
            }
        }


        // 排他思想:
        //  1. 干掉所有人
        //  2. 复活我自己

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

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .box {
        width: 500px;
        height: 400px;
        border: 1px solid #000;
        margin: 100px auto;
    }

    .hd {
        overflow: hidden;
    }

    .hd li {
        width: 25%;
        height: 60px;
        float: left;
        background-color: pink;
        text-align: center;
        line-height: 60px;
        cursor: pointer;
        font-size: 24px;
    }

    .hd li.now {
        background-color: green;
    }

    .bd {
        width: 100%;
        height: 340px;
    }

    .bd div {
        width: 100%;
        height: 100%;
        display: none;
        line-height: 340px;
        text-align: center;
        font-size: 100px;
        background-color: #ccc;
    }

    .bd div.current {
        display: block;
    }
    </style>
</head>

<body>
    <div id="box" class="box">
        <!--导航区-->
        <ul class="hd" id="hd">
            <li class="now" title="0">导航1</li>
            <li title="1">导航2</li>
            <li title="2">导航3</li>
            <li title="3">导航4</li>
        </ul>
        <!--内容区-->
        <div class="bd" id="bd">
            <div class="current">内容1</div>
            <div>内容2</div>
            <div>内容3</div>
            <div>内容4</div>
        </div>
    </div>
    <script>
        // 功能: 
        //  1. 导航区排他
        //  // 思路: 
        //     1.1 找对象 找所有的导航li
        //     1.2 给每一个 li 注册click
        //     1.3 排他
        //      1. 干掉所有人  ==>  把所有的导航li的now类名去掉
        //      2. 复活我自己  ==>  把当前点击的那个li添加上now类名

        // 1.1 
        var lis = document.getElementById("hd").getElementsByTagName("li");
        var divs = document.getElementById("bd").getElementsByTagName("div");

        // 1.2
        for (var i = 0; i < lis.length; i++) {
            lis[i].onclick = function(){

                // 任何一个函数都有属于自己的this

                // 1.3
                // 1.干掉所有人
                for (var i = 0; i < lis.length; i++) {
                    lis[i].className = "";
                }
                // 2.
                this.className = "now";

                // console.log(this.title);  // 当前点击li的title属性,因为title属性上存储了每个li的下标
                // console.log(divs);

                var idx = this.title; // 获取到当前点击那个li的title属性


               // 1. 干掉所有div
                for (var i = 0; i < divs.length; i++) {
                    divs[i].className = "";
                }

                // 2.复活我自己 div
                divs[idx].className = "current";
            }
        }
       
        //  2. 内容区排他 -- 这块排他代码需要写在导航li的点击事件里面
        //   思路: 
        //    1. 干掉所有人  ==>  把所有的div的current 类名去掉
        //    2. 复活我自己  ==>  通过下标取出对应的div添加上current类名

            
        // 小结:
        //  思路:
        //   1. 导航区的排他
        //   2. 内容区的排他
                // 在复活div的时候,让li 和div对应起来,通过下标
                // 哪里来的下标: 给导航li添加了 title属性,该属性用来存储下标
                // 在点击导航的时候,就可以取来出使用了
                // 坑: 千万别忘记给li添加title属性存下标
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .box {
        width: 500px;
        height: 400px;
        border: 1px solid #000;
        margin: 100px auto;
    }

    .hd {
        overflow: hidden;
    }

    .hd li {
        width: 25%;
        height: 60px;
        float: left;
        background-color: pink;
        text-align: center;
        line-height: 60px;
        cursor: pointer;
        font-size: 24px;
    }

    .hd li.now {
        background-color: green;
    }

    .bd {
        width: 100%;
        height: 340px;
    }

    .bd div {
        width: 100%;
        height: 100%;
        display: none;
        line-height: 340px;
        text-align: center;
        font-size: 100px;
        background-color: #ccc;
    }

    .bd div.current {
        display: block;
    }
    </style>
</head>

<body>
    <div id="box" class="box">
        <!--导航区-->
        <ul class="hd" id="hd">
            <li class="now" index="0">导航1</li>
            <li index="1">导航2</li>
            <li index="2">导航3</li>
            <li index="3">导航4</li>
        </ul>
        <!--内容区-->
        <div class="bd" id="bd">
            <div class="current">内容1</div>
            <div>内容2</div>
            <div>内容3</div>
            <div>内容4</div>
        </div>
    </div>
    <script>
        // 功能: 
        //  1. 导航区排他
        //  // 思路: 
        //     1.1 找对象 找所有的导航li
        //     1.2 给每一个 li 注册click
        //     1.3 排他
        //      1. 干掉所有人  ==>  把所有的导航li的now类名去掉
        //      2. 复活我自己  ==>  把当前点击的那个li添加上now类名

        // 1.1 
        var lis = document.getElementById("hd").getElementsByTagName("li");
        var divs = document.getElementById("bd").getElementsByTagName("div");

        // 1.2
        for (var i = 0; i < lis.length; i++) {
            // 给每一个按钮存储下标
            lis[i].index = i;

            lis[i].onclick = function(){
                // 1.3
                // 优化01
                // 1.干掉所有人
                for (var i = 0; i < lis.length; i++) {
                    // 干掉导航li
                    lis[i].className = "";
                    // 干掉div
                    divs[i].className = "";
                }

                // 2.
                this.className = "now";

                // console.log(this.title);  // 当前点击li的title属性,因为title属性上存储了每个li的下标
                // console.log(divs);

                
                // 优化02 在标签上使用index 去存储下标
                // index 是自定义属性,这里不能使用dom对象去操作标签上自定义
                // var idx = this.index; // 获取到当前点击那个li的index属性

                // getAttribute(name)
                var idx = this.getAttribute("index");
                console.log(idx);

                // 1. 干掉所有div
                // 2.复活我自己 div
                divs[idx].className = "current";
            }
        }
       
        //  2. 内容区排他 -- 这块排他代码需要写在导航li的点击事件里面
        //   思路: 
        //    1. 干掉所有人  ==>  把所有的div的current 类名去掉
        //    2. 复活我自己  ==>  通过下标取出对应的div添加上current类名

            
        // 小结:
        //  思路:
        //   1. 导航区的排他
        //   2. 内容区的排他
                // 在复活div的时候,让li 和div对应起来,通过下标
                // 哪里来的下标: 给导航li添加了 title属性,该属性用来存储下标
                // 在点击导航的时候,就可以取来出使用了
                // 坑: 千万别忘记给li添加title属性存下标
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .box {
        width: 500px;
        height: 400px;
        border: 1px solid #000;
        margin: 100px auto;
    }

    .hd {
        overflow: hidden;
    }

    .hd li {
        width: 25%;
        height: 60px;
        float: left;
        background-color: pink;
        text-align: center;
        line-height: 60px;
        cursor: pointer;
        font-size: 24px;
    }

    .hd li.now {
        background-color: green;
    }

    .bd {
        width: 100%;
        height: 340px;
    }

    .bd div {
        width: 100%;
        height: 100%;
        display: none;
        line-height: 340px;
        text-align: center;
        font-size: 100px;
        background-color: #ccc;
    }

    .bd div.current {
        display: block;
    }
    </style>
</head>

<body>
    <div id="box" class="box">
        <!--导航区-->
        <ul class="hd" id="hd">
            <li class="now">导航1</li>
            <li>导航2</li>
            <li>导航3</li>
            <li>导航4</li>
        </ul>
        <!--内容区-->
        <div class="bd" id="bd">
            <div class="current">内容1</div>
            <div>内容2</div>
            <div>内容3</div>
            <div>内容4</div>
        </div>
    </div>
    <script>
        // 功能: 
        //  1. 导航区排他
        //  // 思路: 
        //     1.1 找对象 找所有的导航li
        //     1.2 给每一个 li 注册click
        //     1.3 排他
        //      1. 干掉所有人  ==>  把所有的导航li的now类名去掉
        //      2. 复活我自己  ==>  把当前点击的那个li添加上now类名

        // 1.1 
        var lis = document.getElementById("hd").getElementsByTagName("li");
        var divs = document.getElementById("bd").getElementsByTagName("div");

        // 1.2
        for (var i = 0; i < lis.length; i++) {
            // 给每一个按钮存储下标
            lis[i].index = i;

            lis[i].onclick = function(){
                // 任何一个函数都有属于自己的this
                // 1.3
                // 优化01
                // 1.干掉所有人
                for (var i = 0; i < lis.length; i++) {
                    // 干掉导航li
                    lis[i].className = "";
                    // 干掉div
                    divs[i].className = "";
                }

                // 2.
                this.className = "now";

                // console.log(this.title);  // 当前点击li的title属性,因为title属性上存储了每个li的下标
                // console.log(divs);

                // 优化02 在标签上使用index 去存储下标
                var idx = this.index;
                console.log(idx);

                // 1. 干掉所有div
                // 2.复活我自己 div
                divs[idx].className = "current";
            }
        }
       
        //  2. 内容区排他 -- 这块排他代码需要写在导航li的点击事件里面
        //   思路: 
        //    1. 干掉所有人  ==>  把所有的div的current 类名去掉
        //    2. 复活我自己  ==>  通过下标取出对应的div添加上current类名

            
        // 小结:
        //  思路:
        //   1. 导航区的排他
        //   2. 内容区的排他
                // 在复活div的时候,让li 和div对应起来,通过下标
                // 哪里来的下标: 给导航li添加了 title属性,该属性用来存储下标
                // 在点击导航的时候,就可以取来出使用了
                // 坑: 千万别忘记给li添加title属性存下标
    </script>
</body>

</html>

5.标签的内容属性

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>
    <button>按钮</button>

    <script>
        // 需求: 点击按钮的时候,获取当前按钮的下标
        // 第一个下标就是0

        var btns = document.getElementsByTagName("button");

        // 01
        /*for (var i = 0; i < btns.length; i++) {
            // i // 0-9
            // 这是给每一个按钮添加index 属性,该属性值是i,对应的就是每个按钮自己的下标
            btns[i].setAttribute("index", i);  // 存下标

            // 这是给每一个按钮注册点击事件
            btns[i].onclick = function () {
                console.log(this.getAttribute("index"));  // 取当前按钮的下标
            }
        }*/


        // 更加简洁的做法
        // 02
        for (var i = 0; i < btns.length; i++) {
            // i // 0-9
            // 给dom对象添加index属性,值就是对应的i
            // 给dom对象存的,标签上没有index,因为index属性是自定义的
            btns[i].index = i;

            console.dir(btns[i]);

            // 这是给每一个按钮注册点击事件
            btns[i].onclick = function () {
                // 这是通过dom对象的形式去获取index属性
                console.log(this.index); // 取当前按钮的下标
            }
        }



        // 小结:
        //  存下标 ,不是手动给按钮添加title 、index属性
        //  通过jsfor循环给每一个按钮添加index属性
        //      1.1 setAttribute 来设置   getAttribute 来获取, 存在标签上
        //      1.2 把index属性存在dom对象上,通过dom对象去获取index属性
    </script>
</body>
</html>

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

    
    <div id="box">
        <h1>这是标题内容</h1>
    </div>

    <script>
        // 标签的内容属性

        // 这两个属性都是用来操作文本内容
        // innerText
        // innerHTML

        var box = document.getElementById("box");

        // 获取内容
        // innerText 不识别标签,获取内容只能获取纯文本
        // innerHTML 能识别标签,获取内容可以获取到标签
        // console.log(box.innerText);
        // console.log(box.innerHTML);


        // 设置内容(纯文本)
        // 共同点: 在设置内容的时候,会覆盖标签中默认的内容
        // box.innerText = "哈哈";
        // box.innerHTML = "哈哈";


        // 设置内容(带标签)
        // innerText 不能识别标签,设置内容的时候,把标签给转义了,标签成了普通文本
        // innerHTML 可以识别标签,在设置内容的时候,标签可以起效果。
        // box.innerText = "<h2>这是新的h2内容</h2>";
        box.innerHTML = "<h3>这是新的h2内容</h3>";



        // 小结:  操作文本内容
        //  获取: innerText 不能识别标签,innerHTML 可以识别标签 
        //  设置: 
        //      共同点:设置的时候都会覆盖标签原来的内容
        //      不同点: innerText设置标签,当做普通文本
        //              innerHTML ,标签起效果

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


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

    <div id="box" style="border: 1px solid #000; padding: 10px;"></div>

    <textarea id="txt" name="" id="" cols="60" rows="20"></textarea>
    
    <button id="btn">发布</button>



    <script>
        // 操作文本内容的使用场景

        // innerText   innerHTML
        //  对于不需要识别标签的时候,使用innerText
        //  对于需要识别标签的时候,使用innerHTML
        // 建议,推荐使用innerText, 主要安全考虑

        var btn = document.getElementById("btn");
        var box = document.getElementById("box");
        var txt = document.getElementById("txt");


        // 点击按钮,发布文本域的内容设置到div内
        btn.onclick = function () {
            // 对于 textarea来说,内容是通过value属性来获取的,不是innerText
            // console.log(txt.value);

            box.innerText = txt.value;
        }





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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="box">哈哈</div>

    <script>
        // innerText的浏览器兼容性问题
        // 1. 标签、css样式
        // 2. js中的属性和方法

        // innerHTML: 该属性是W3C推荐用来操作文本内容的属性
        // innerText: 是IE自己弄出来的属性,低版本的火狐浏览器就不支持该属性
        // textContent: 是火狐浏览器自己提出来,低版本的ie(678) 浏览器不支持该属性


        var box = document.getElementById("box");

        // 对于现代浏览器来说,innerText 、 textContent 都支持了
        // console.log(box.innerHTML); // 该属性没有兼容性问题
        // console.log(box.innerText);
        // console.log(box.textContent);


        // 处理兼容性问题:  能力检测: you can you up

        // 封装起来, getTxt()
        function getTxt(element){
            if(typeof element.innerText == "string"){
                // 说明该浏览器支持innerText属性去操作文本内容
                return element.innerText;
            }else{
                // 不支持innerText
                return element.textContent;
            }
        }
        var ret = getTxt(box)
        console.log(ret);


        // 小结:
        //  兼容性问题:
        //      innerText 存在兼容性  innerHTML
        //      textContent

        // 处理: 能力检测   做判断
    </script>
</body>
</html>

四、获取元素的方法

1.根据id获取

在这里插入图片描述

2.根据标签名获取

在这里插入图片描述

3.根据类名获取

在这里插入图片描述

4.根据name获取

在这里插入图片描述

5.根据css选择器获取

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <div id="box">
        <p class="demo">123</p>
        <p class="demo">123</p>
        <p class="demo">123</p>
        <span class="demo">345</span>
        <span class="demo">345</span>
        <span class="demo">345</span>
    </div>


    <form action="">
        <input type="text" name="age">
        <input type="text" name="username">
        <input type="text" name="age">
    </form>

    <script>
        // 1. getElementById(id)
        //  参数: id名称
        //  返回值: 获取到的元素, 没有获取到元素返回null

        // 2. getElementsByTagName()
        //  参数: 标签名
        //  返回值: 伪数组

        // 3. getElementsByClassName();  // 通过类名来获取元素
        //  参数: 类名
        //  返回值: 伪数组

        // 该方法存在兼容性问题: IE678不支持
        // var res = document.getElementsByClassName("demo");
        // console.log(res);


        // 4. getElementsByName(name); // 该方法只支持表单元素,因为表单元素才有name属性
        // var res = document.getElementsByName("age");
        // console.log(res);

        // 5. 这两个方法可以通过css选择器来获取元素
        //      IE低版本也是不支持
        // Selector: 选择器    div  .dmeo  #box  #box > li   #box li.dmeo
        // document.querySelector(selectors)
        //  参数: 是选择器
        // 返回值: 返回获取到的元素, 仅仅只会返回获取到的元素的第一个(不管能获取到多少个元素,只会返回第一个)

        // 注意点: id选择器需要带#
        // var res = document.querySelector("#box");

        // var res = document.querySelector(".demo");
        

        // 区别: 能够通过选择器获取到所有的元素,返回值返回了一个伪数组
        //      伪数组,没有获取到元素,返回空的伪数组
        // document.querySelectorAll(selectors)

        var res= document.querySelectorAll("#box > .demo");
        console.log(res);



        // 小结:
        //  1. document.getElementById()
        //  2. 通过标签名来找
        //  3. 通过类名来获取
        //  4. 通过name属性来获取
        //  5. 通过选择器来获取
        //      document.querySelector  ==> 找第一个
        //      document.querySelectorAll ==> 找所有的, 返回伪数组


        // 注意下面两者不要混淆
        // document.getElementById("box");  ==> 已经指定通过id来获取元素了,所以不要加#
        // document.querySelector("#box");  ==> 通过css选择器来获取元素, 必须要加上#才能通过id找元素
    </script>
</body>
</html>

五、样式操作(style属性)

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .red {
            background-color: red;
        }

        .box {
            width: 100px;
            height: 100px;
            background-color: #f00;
        }
    </style>
</head>

<body>
    <div id="box" class="box"></div>

    <script>
        // style属性  相比较通过类名来设置样式,要灵活些

        // style 属性是固有的属性,所有dom对象中也有对应的style属性

        var box = document.querySelector("#box");

        // 获取style属性,  是一个对象,对象里面的属性是元素的所有的行内样式
        console.log(box.style);

        // // 获取的是元素的行内样式
        // console.log(box.style.width);
        // console.log(box.style.height);
        // // 在标签中backgroundColor 是-连接的,但是在style对象中,必须要写成 backgroundColor(驼峰式)
        // // 因为-在js中不是个合格的标识符
        // console.log(box.style.backgroundColor);



        // 设置行内样式,注意,单位问题
        box.style.width = "300px";
        box.style.height = "300px";
        box.style.backgroundColor = "#f99";


        // style 仅仅操作的元素的行内样式(获取和设置都是属于行内的)


        // 小结:
        //  1. style 属性  标签中的固有属性,dom对象中也有该属性
        //  2. dom对象中style属性值是一个对象
        //  3. style对象存储着元素的所有的行内样式
        //  4. style去获取样式,仅仅只会获取到行内样式
        //  5. style去设置样式, 设置的也是行内样式







        // 学费: 20000
        // 一个月开销: 2000 * 6  = 12000
        // 工作: 5000 * 6 = 30000
        // 总结: 花了  62000 / 180 ==>  300
        // 10k+
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button>关灯</button>

    <script>
        // 思路:
        //  1. 找对象 按钮
        //  2. 按钮注册 click
        //  3. 根据按钮的文字去做判断
        //      文字 == 关灯
        //          把 body的背景颜色变成黑色
        //          把按钮的文字变成 开灯
        //          
        //      文字 == 开灯
        //          把 body的背景颜色变成白色
        //          把按钮的文字变成 关灯

        // 1.
        var btn = document.querySelector("button");
        // 通过标签名去获取body元素
        // var body = document.querySelector("body");

        // 2./
        btn.onclick = function () {
            // 3.
            if (this.innerText == "关灯") {
                // 把 body的背景颜色变成黑色
                document.body.style.backgroundColor = "#000";
                // 把按钮的文字变成 开灯
                this.innerText = "开灯"
            }else{
                //          把 body的背景颜色变成白色
                document.body.style.backgroundColor = "#fff";
                //          把按钮的文字变成 关灯
                this.innerText = "关灯";
            }
        }
        // style 去设置行内样式
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>页面标题</title>
</head>
<body>
    <script>
        // document  文档
        //  html ==> document.documentElement
        //  body ==>  document.body
        //  head ==> document.head
        //  title ==> document.title

        console.log(document.body);
        console.log( document.head);
        console.log(document.title); // 获取title内容

        // document.title = "新的标题内容";
        console.log(document.documentElement);
    </script>
</body>
</html>

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
    * {
        padding: 0;
        margin: 0;
    }

    .wrap {
        width: 500px;
        margin: 100px auto 0;
    }

    table {
        border-collapse: collapse;
        border-spacing: 0;
        border: 1px solid #c0c0c0;
        width: 500px;
    }

    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:nth-child(odd) {
      background-color: lime;
    }
    
    tbody tr:nth-child(even) {
      background-color: yellowgreen;
    }
    
    tbody tr:hover {
      background-color: red;
    } */
    </style>
</head>

<body>
    <div class="wrap">
        <table>
            <thead>
                <tr>
                    <th>序号</th>
                    <th>姓名</th>
                    <th>课程</th>
                    <th>成绩</th>
                </tr>
            </thead>
            <tbody id="j_tb">
                <tr>
                    <td>
                        1
                    </td>
                    <td>柳岩</td>
                    <td>语文</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>
                        2
                    </td>
                    <td>苍老师</td>
                    <td>日语</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>
                        3
                    </td>
                    <td>凤姐</td>
                    <td>营销学</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>
                        4
                    </td>
                    <td>张飞</td>
                    <td>数学</td>
                    <td>10</td>
                </tr>
                <tr>
                    <td>
                        5
                    </td>
                    <td>小沈阳</td>
                    <td>英语</td>
                    <td>100</td>
                </tr>
                <tr>
                    <td>
                        6
                    </td>
                    <td>马户</td>
                    <td>体育</td>
                    <td>100</td>
                </tr>
            </tbody>
        </table>
    </div>
    <script>
    // 功能:
    //   1. 隔行变色
    // 思路:
    //  1. 找对象 tr
    //  2. for循环遍历

    // 1. 
    var trs = document.querySelectorAll("#j_tb tr");
    var oldColor; // 记录当前鼠标移入上去的那个tr的背景颜色

    // 2.
    for (var i = 0; i < trs.length; i++) {
        /*// 隔行变色的功能
        if (i % 2 == 0) {
            // 下标为偶数的
            trs[i].style.backgroundColor = "yellow";
        } else {
            trs[i].style.backgroundColor = "green";
        }*/


        /*// 注册鼠标移入移出
        trs[i].onmouseover = function() {
            // 把当前的tr的背景颜色给存储到变量
            oldColor = this.style.backgroundColor;
            // 这两行代码顺序不能反过来,否则效果不对
            this.style.backgroundColor = "red";
        }

        trs[i].onmouseout = function() {
            // 恢复成默认的背景颜色
            this.style.backgroundColor = oldColor;

            // 这种error,表示把背景颜色变成空白了,没有背景颜色了
            // this.style.backgroundColor = "";
        }*/
    }

    //   2. 鼠标移入移出 变色
    //      移入高亮 red
    //      移出 : 恢复成默认的背景颜色
    //   思路: 
    //   2.1 给每一个tr注册 onmouseover 。高亮
    //   2.2 给每一个tr 注册 onmouseout  。 恢复成默认的背景颜色

    for (var i = 0; i < trs.length; i++) {
        trs[i].onmouseover
    }
    </script>
</body>

</html>

六、节点操作

1.节点的属性

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <div id="box">
            <!-- 注释 -->
            <p>这是谁放的</p>
            <h1>这是标题</h1>
        </div>

        <script>
            // dom  文档树模型

            // dom树存在的作用: 方便找亲戚,方便对节点进行操作(添加节点、删除。。。)
        </script>
    </body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <ul>
        <!-- 这是注释节点 -->
        <li>这是第1个li元素</li>
        <li>这是第2个li元素</li>
        <li>这是第3个li元素</li>
    </ul>

    <script>
        // 节点的属性

        var ul = document.querySelector("ul");

        // childNodes   ==> 该属性可以用来获取节点的所有子节点
        // 节点: 任何内容(标签、属性、注释、文本)


        // 节点的属性
        //  nodeName:  节点的名称
        //  nodeType : 节点的类型,用数字表示  ,标签节点的是 1
        //  nodeValue: 节点的值

        console.log(ul.childNodes[0]);  // 文本节点
        console.dir(ul.childNodes[1]);  // 注释节点
        console.dir(ul.childNodes[3]);  // 标签节点


        // 标签节点的属性比其他的节点属性多,多的是on系列的事件。只有标签才可以注册事件
    </script>
</body>
</html>

2.节点查找

孩子节点

在这里插入图片描述

兄弟节点

在这里插入图片描述

父节点

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <ul>
        <!-- 这是注释节点 -->
        <li>这是第1个li元素</li>
        <li id="two">这是第2个li元素</li>
        <li>这是第3个li元素</li>
    </ul>

    <script>
        // childNodes 可以用来获取所有的子节点
        // children 属性可以获取标签节点

        var ul = document.querySelector("ul");
        var two = document.querySelector("#two");


        // 孩子
        // console.log(ul.childNodes);
        // IE678有bug,会把注释节点计算在内
        // console.log(ul.children);

        // firstChild ==> 获取第一个子节点
        // IE678不支持
        // firstElementChild ==> 获取第一个子元素
        // console.log(ul.firstChild); // 
        // console.log(ul.firstElementChild);


        // lastChild  ==> 获取最后一个子节点
        // lastElementChild ==> 获取最后一个子元素
        // console.log(ul.lastChild);
        // console.log(ul.lastElementChild);


        // 兄弟节点关系
        // previousSibling  ==> 上一个兄弟节点
        // previousElementSibling  ==> 上一个兄弟元素
        // console.log(two.previousSibling);
        // console.log(two.previousElementSibling);


        // nextSibling  ==> 下一个兄弟节点
        // nextElementSibling  ==> 下一个兄弟元素
        // console.log(two.nextSibling);
        // console.log(two.nextElementSibling);



        // 父辈  parentNode  父节点 父元素
        console.log(two.parentNode);


        // 小结:
        //  1. 找孩子: 
        //      childNodes  子节点
        //      children : 子元素
        //      firstChild  : 第一个子节点
        //      firstElementChild:  第一个子元素
        //      lastChild
        //      lastElementChild:  最后一个子元素

        //  2. 找兄弟
                // previousSibling:  上一个兄弟节点
                // previousElementSibling  上一个兄弟元素
                // nextSibling
                // nextElementSibling   下一个兄弟元素

        //  3. 找父辈
                // parentNode
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    * {
        margin: 0;
        padding: 0;
    }
    </style>
</head>

<body>
    <div id="box">
        <!--注释-->
        <p>1</p>
        <p>1</p>
        <p>1</p>
        <div>2</div>
        <div>2</div>
        <div>2</div>
    </div>
    <script>
    //需求:让box中的元素(p div)隔行变色

    // childNodes 找所有的子节点
    // children 找子元素

    var box = document.querySelector("#box");

    var childEles = box.children;
    // console.log(childEles);

    for (var i = 0; i < childEles.length; i++) {
      if(i % 2 == 0){
        childEles[i].style.backgroundColor = "pink";
      }else{
        childEles[i].style.backgroundColor = "#f99";
      }
    }
    
    </script>
</body>

</html>

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>1个li元素</li>
        <li>2个li元素</li>
        <li id="box">3个li元素</li>
        <li>4个li元素</li>
    </ul>
    <script>
        // previousElementSibling 的兼容性处理

        if (!("previousElementSibling" in document.documentElement)) {
            Object.defineProperty(Element.prototype, "previousElementSibling", {
                get: function() {
                    var e = this.previousSibling;
                    while (e && 1 !== e.nodeType) {
                        e = e.previousSibling;
                    }
                    return e;
                }
            });
        }

        var box = document.querySelector("#box");
        console.log(box.previousElementSibling.innerText);
    </script>
</body>

</html>

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

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    #list li {
        list-style-type: none;
        width: 80px;
        height: 30px;
        line-height: 30px;
        background-color: beige;
        text-align: center;
        float: left;
        margin-left: 5px;
    }

    #list li.current {
        background-color: burlywood;
    }

    #list li a {
        text-decoration: none;
        display: block;
        width: 100%;
        height: 100%;
    }
    </style>
</head>

<body>
    <div id="menu">
        <ul id="list">
            <li class="current">
                <a href="javascript:void(0);">首页</a>
            </li>
            <li><a href="javascript:void(0);">播客</a></li>
            <li><a href="javascript:void(0);">博客</a></li>
            <li><a href="javascript:void(0);">相册</a></li>
            <li><a href="javascript:void(0);">关于</a></li>
            <li><a href="javascript:void(0);">帮助</a></li>
        </ul>
    </div>
    <script>
        // 功能: 菜单排他

        // a 链接上href 属性值 javascript:void(0);
        // href="javascript:;" ==> 表示a链接不尽兴跳转,执行js代码
        // void(0)  ==>  不执行任何操作


        // 思路: 
        //  1. 找对象
        //  2. for循环 给每一个li注册click
        //  3. 排他,让当前的菜单li 高亮 添加current类名

        // 1.
        // var lis = document.querySelectorAll("#list li");

        var ul = document.querySelector("#list");
        var lis = ul.children;
    
        // 2.
        for (var i = 0; i < lis.length; i++) {
            lis[i].onclick = function () {
                // 3.

                // 1. 干掉所有人 -- 把所有的li的current类名去掉
                for (var i = 0; i < lis.length; i++) {
                    lis[i].className = "";
                }

                // 2. 复活我自己 -- 给当前的li添加current类名
                this.className = "current";
            }
        }


        // 小结:
        //  阻止a链接的跳转两种方式:
        //   1. 给a注册click事件,在事件处理函数里面 return false
        //   2. a href 属性值为 javascript:void(0);
    </script>
</body>

</html>

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

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    #list li {
        list-style-type: none;
        width: 80px;
        height: 30px;
        line-height: 30px;
        background-color: beige;
        text-align: center;
        float: left;
        margin-left: 5px;
    }

    #list li.current {
        background-color: burlywood;
    }

    #list li a {
        text-decoration: none;
        display: block;
        width: 100%;
        height: 100%;
    }
    </style>
</head>

<body>
    <div id="menu">
        <ul id="list">
            <li class="current">
                <a href="javascript:void(0);">首页</a>
            </li>
            <li><a href="javascript:void(0);">播客</a></li>
            <li><a href="javascript:void(0);">博客</a></li>
            <li><a href="javascript:void(0);">相册</a></li>
            <li><a href="javascript:void(0);">关于</a></li>
            <li><a href="javascript:void(0);">帮助</a></li>
        </ul>
    </div>
    <script>
        // 功能: 菜单排他

        // a 链接上href 属性值 javascript:void(0);
        // href="javascript:;" ==> 表示a链接不尽兴跳转,执行js代码
        // void(0)  ==>  不执行任何操作


        // 思路: 
        //  1. 找对象  a
        //  2. for循环 给每一个a注册click
        //  3. 排他,让当前的菜单li 高亮 添加current类名

        // 1.
        var as = document.querySelectorAll("#list a");

        // 2.
        for (var i = 0; i < as.length; i++) {
            as[i].onclick = function () {
                // 3.
                for (var i = 0; i < as.length; i++) {
                    as[i].parentNode.className = "";
                }

                // this ==> a
                this.parentNode.className = "current";
            }
        }

        // 小结:
        //  阻止a链接的跳转两种方式:
        //   1. 给a注册click事件,在事件处理函数里面 return false
        //   2. a href 属性值为 javascript:void(0);
    </script>
</body>

</html>

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

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

<body>
    用户名:<input type="text" id="txtName"><span></span><br>
    密码:<input type="password" id="txtPwd"><span></span><br>
    <script>
        // 新的事件:
        //  onkeyup 当键盘弹起的时候
        //  onkeydown: 当键盘摁下的时候触发

        // 必须要在事件中获取到输入框内的内容,判断内容的长度是否符合需求

        // var txtName = document.querySelector("#txtName");
        /*txtName.onkeydown = function () {
            // console.log("键盘按下去了");
            console.log(txtName.value);
        }*/

        /*txtName.onkeyup = function () {
            // console.log("键盘弹起来了");

            console.log(txtName.value);
        }*/


        // onkeyup  onkeydown 在获取input内容的时候,区别:
        //  onkeydown 获取的是上一次的内容(不是完整的内容)
        //  onkeyup   获取的内容是完整的。






        // 思路:
        //  1. 找对象  
        //  2. input 注册 onkeyup(可以在该事件中获取input完整的value值)
        //  3. 获取内容,判读内容的长度是否符合2-6位之间

        // 1.
        var txtName = document.querySelector("#txtName");

        // 2.
        txtName.onkeyup = function () {
            // 3.
            var txt = this.value;

            if(txt.length < 2 || txt.length > 6){
                // 不符合需求:
                // this.nextElementSibling==> 找到input的兄弟span元素
                this.nextElementSibling.innerText = "用户名需要在2-6位之间";
                this.nextElementSibling.style.color = "red";
            }else{
                // 符合需求:
                this.nextElementSibling.innerText = "正确";
                this.nextElementSibling.style.color = "green";
            }
        }

        // 小结:
        //  onkeyup 注册事件
        //  nextElementSibling 找span元素

    </script>
</body>

</html>

3.添加节点

appendChild

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <div id="box" style="padding: 20px; border: 1px solid #000;">
        <h1>这是h1标题</h1>
    </div>

    <p>这是p元素</p>

    <script>
        // 添加节点
        // appendChild
        // 语法: parent.appendChild(child)
        // 参数:
        //  parent  指定的父元素
        //  child   指定的子元素,添加到父元素的里面的最后面

        // 注意点: 
        //  参数child 是页面中本来就存在的元素,那么添加就是剪切的效果

        var box = document.querySelector("#box");
        var p = document.querySelector("p");

        box.appendChild(p);
    </script>
</body>
</html>

insertBefore

在这里插入图片描述

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

    <div id="box">
        <span>span元素</span>
        <h1>这是h1标题</h1>
        <h2>这是h2标题</h2>
    </div>
    
    <p>这是div外的p元素</p>


    <script>
        // insertBefore() 添加节点到任意的位置
        // 语法: parent.insertBefore(child, refChild)
        // parent: 父元素
        // child: 需要添加的节点
        // refChild: 添加在该参数的前面
        // 两个参数必须都写上

        var box = document.querySelector("#box");
        var h2 = document.querySelector("h2");
        var p = document.querySelector("p");

        // box.insertBefore(p, h2);  // p添加到h2的前面
        // box.insertBefore(p, box.firstElementChild);  // p添加到span的前面
        // box.insertBefore(p, box.children[0]);  // p添加到span的前面
            
        // 该方法必须是两个参数
        // box.insertBefore(p);  // error


        //  第二个参数为null、undefined ,这样的该方法的作用同 appendChild 
        box.insertBefore(p, undefined);  


        // 小结: 添加节点
        //  1. parent.appendChild(child) 
        //  2. parent.insertBefore(child, refChild)
        //  
        //  共同点:这两个方法必须是parent父元素去调用方法 
    </script>
</body>
</html>

4.克隆节点

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <p id="box">
        <span>这是span内额</span>
    </p>

    <script>
        // 克隆节点
        // 语法: node.cloneNode(deep)
        // 参数: node : 克隆的节点
        //          deep: 布尔类型的值
        //              true: 表示深拷贝:不仅仅要拷贝标签,还要拷贝标签里面的标签和内容
        //              false: 浅拷贝: 只会克隆标签自身
        //              有默认值,默认值为false

        // 返回值: 克隆出来的元素,在内存中

        var p = document.querySelector("p");

        var newP = p.cloneNode(true);
        // 注意点: 如果克隆元素带id,那么需要对克隆出来的元素做id修改

        // 克隆出来的元素和原来的元素就没有关系了,之间的修改互不影响
        newP.id = "box2";
        console.log(newP);
        document.body.appendChild(newP);


        // 小结:
        //  node.cloneNode(deep)
        //      deep决定深拷贝还是浅拷贝
        //  克隆出来的元素和原来就没有关系了
        //  id问题,id不能重名
        //  克隆出来的只是在内存中,页面中看不到
    </script>
</body>
</html>

5.删除节点

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <ul>
        <li>堂哥</li>
        <li>大聪哥</li>
        <li>莲妹</li>
    </ul>

    <script>
        // removeChild()
        // 语法: parent.removeChild(child)
        // 该方法必须由parent父元素去调用,参数为需要删除的子元素
            
        // 需求: 点击哪个li,从ul中移除当前点击的li

        var lis = document.querySelectorAll("li");

        for(var i = 0; i < lis.length; i++){
            lis[i].onclick = function () {
                // 不能是this去调用,然后删除this
                // this.removeChild()
                this.parentNode.removeChild(this);
            }
        }            


        // 小结:
        //  removeChild 和 display:none; 
        //    display:none;  只是看不见隐藏了,在dom树还是存在的
        //    removeChild: 真的就是从dom树移除了
    </script>
</body>
</html>

6.创建节点(3种方式)

document.write(基本不用)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    这是本来的内容
    
    <button>点击我,写入内容</button>

    <script>
        // 创建节点

        // 1. document.write

        var btn = document.querySelector("button");

        btn.onclick = function () {
            // document.write 写入内容存在覆盖问题
            document.write("<h1>这是我使用js写入的内容</h1>");
        }


        // 小结: 
        //  document.write() 不用

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

innerHTML

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="box" style="width: 300px; height: 300px; border: 1px solid #000;">
        这是div本来就有的内容
    </div>

    <script>
        // innerHTML 去创建标签节点,原理: 识别标签
        //  innerHTML 可以创建标签,但是用的不多
        //      1. 存在覆盖问题:会把标签之前的内容给覆盖掉
        //      2. 存在效率问题

        var box = document.querySelector("#box");

        box.innerHTML += "<h1>这是设置的标签</h1>";
    </script>
</body>
</html>

createElement

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <div id="box" style="width: 300px; height: 300px; border: 1px solid #000;">
        这是div本来就有的内容
    </div>

    <script>
        // 语法: document.createElement(tagName)
        // 参数: 标签名
        // 返回值: 创建好的标签,存在内存中

        var box = document.querySelector("#box");
        var h1Node = document.createElement("h1");
        h1Node.innerText = "这是设置的内容";

        box.appendChild(h1Node);

        // 小结:
        //  创建标签节点
        //   1. document.wirte()
        //   2. innerHTML 原理: 识别标签
        //   3. createElement("div")

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

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <script>
    // 需求: 往body中创建添加1000个按钮

    // innerHTML 去使用
    // 优化的作用: 
    //  建议: 不要在for循环中大量的使用innerHTML
    /*var start = new Date();
    for(var i = 0; i < 1000; i++){
        var btn = '<button type="button">按钮</button>';
        document.body.innerHTML += btn;
    }
    var end = new Date();
    console.log(end - start);  // 1500ms*/


    // 优化innerHTML的作用

    var str = ""; // 保存所有的按钮

    var start = new Date();
    for (var i = 0; i < 1000; i++) {
        var btn = '<button type="button">按钮</button>';

        str += btn;
    }
    // console.log(str); // 1000个按钮的字符串形式
    // 在循环之后,将拼接好的字符串一次性设置给innerHTML
    document.body.innerHTML = str;
    var end = new Date();
    console.log(end - start); // 6ms



    // createElement 
    /*var start = new Date();
    for(var i = 0; i < 1000; i++){
        var btn = document.createElement("button");
        btn.innerText = "按钮";
        document.body.appendChild(btn);
    }
    var end = new Date();
    console.log(end - start);  // 4ms*/


    // 小结:
    //  innerHTML  createElement 的效率问题
    </script>
</body>

</html>

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    div {
        width: 400px;
        height: 400px;
        border: 1px solid #000;
    }
    </style>
</head>

<body>
    <button>生成</button>
    <div>
       
    </div>
    <script>
        // 模拟了数据
        var arr = [
           
        ]


        // 思路: 
        // 1. 找对象 按钮  +  div
        // 2. 给按钮注册click
        // 3. 创建ul, 添加到div内
        // 4. 创建li, li添加ul中, 根据arr的长度去创建li
        // 5. 设置li的内容,li内容来源arr

        // 1.
        var btn = document.querySelector("button");
        var div = document.querySelector("div");

        // 2.
        btn.onclick = function () {
            // 3.
            var ulNode = document.createElement("ul");
            div.appendChild(ulNode);

            // 4.
            for (var i = 0; i < arr.length; i++) {
                var liNode = document.createElement("li");
                liNode.innerText = arr[i];

                // 设置背景颜色 -- 优化的做法
                // 直接设置背景颜色
                if(i % 2 == 0){
                    liNode.style.backgroundColor = "lime";
                }else{
                    liNode.style.backgroundColor = "yellow";
                }

                ulNode.appendChild(liNode);
            }

            // 隔行变色 , 写在click事件内,创建好了li在隔行变色
            // 1. 找到所有的li
            // 2. for循环

            /*var lis = ulNode.children;
            for (var i = 0; i < lis.length; i++) {
                if(i % 2 == 0){
                    lis[i].style.backgroundColor = "lime";
                }else{
                    lis[i].style.backgroundColor = "yellow";
                }
            }*/
        }







    </script>
</body>

</html>

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
    * {
        margin: 0;
        padding: 0;
    }

    ul {
        list-style: none;
    }

    .box {
        width: 600px;
        margin: 100px auto;
        border: 1px solid #000;
        padding: 20px;
    }

    textarea {
        width: 450px;
        height: 160px;
        outline: none;
        resize: none;
    }

    ul {
        width: 450px;
        padding-left: 80px;
    }

    ul li {
        line-height: 25px;
        border-bottom: 1px dashed #cccccc;
    }

    input {
        float: right;
    }
    </style>
</head>

<body>
    <div class="box" id="weibo">
        <span>微博发布</span>
        <textarea name="" id="txt" cols="30" rows="10"></textarea>
        <button id="btn">发布</button>
        <ul id="ul">
        </ul>
    </div>
    <script>
      // 思路: 
      // 1. 找对象 txt btn ul
      // 2. 给btn 注册 click
      // 3. 创建li li的内容来源于txt的内容
      // 4. 将li添加到ul中
      // 5. 创建删除按钮, 添加到li
      // 6. 给删除按钮注册click
      // 7. 移除当前的li

      // 1.
      var txt = document.querySelector("#txt");
      var btn = document.querySelector("#btn");
      var ul = document.querySelector("#ul");

      // 2.
      btn.onclick = function () {
        var val = txt.value;

        // 3,.
        var liNode = document.createElement("li");
        liNode.innerText = val;
        
        

        // 4.
        // ul.appendChild(liNode); // 这是往后面添加的
        ul.insertBefore(liNode, ul.children[0]);
      }


      // 小结:
      //  1. createElement
      //  2. insertBefore 添加节点,指定添加的位置

    </script>
</body>

</html>

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
    * {
        margin: 0;
        padding: 0;
    }

    ul {
        list-style: none;
    }

    .box {
        width: 600px;
        margin: 100px auto;
        border: 1px solid #000;
        padding: 20px;
    }

    textarea {
        width: 450px;
        height: 160px;
        outline: none;
        resize: none;
    }

    ul {
        width: 450px;
        padding-left: 80px;
    }

    ul li {
        line-height: 25px;
        border-bottom: 1px dashed #cccccc;
    }

    input {
        float: right;
    }
    </style>
</head>

<body>
    <div class="box" id="weibo">
        <span>微博发布</span>
        <textarea name="" id="txt" cols="30" rows="10"></textarea>
        <button id="btn">发布</button>
        <ul id="ul">
        </ul>
    </div>
    <script>
      // 思路: 
      // 1. 找对象 txt btn ul
      // 2. 给btn 注册 click
      // 3. 创建li li的内容来源于txt的内容
      // 4. 将li添加到ul中
      // 5. 创建删除按钮, 添加到li
      // 6. 给删除按钮注册click
      // 7. 移除当前的li
      // 8. 在点击发布之后,需要清除txt的内容
      // 9. 判断txt的内容是否为空。如果为空,就不执行后续操作
      //      创建li button 。。。

      // 1.
      var txt = document.querySelector("#txt");
      var btn = document.querySelector("#btn");
      var ul = document.querySelector("#ul");

      // 2.
      btn.onclick = function () {
        var val = txt.value.trim();

        // 8.清除txt的内容
        txt.value = "";

        // 坑: 这是把 val变量刚存储的值变成""
        // val = "";

        if(val.length == 0){
          // 啥都没写
          return;  // return后面不执行
        }


        // 3,.
        var liNode = document.createElement("li");
        liNode.innerText = val;
        
        // 5.
        var button = document.createElement("button");
        button.innerText = "删除";
        button.style.float = "right";

        // 6. 设置点击事件
        button.onclick = function () {
          // 7.
          // this ==> 按钮
          ul.removeChild(this.parentNode);
        }

        liNode.appendChild(button);

        // 4.
        // ul.appendChild(liNode); // 这是往后面添加的
        ul.insertBefore(liNode, ul.children[0]);
      }


      // 小结:
      //  1. createElement
      //  2. insertBefore 添加节点,指定添加的位置

    </script>
</body>

</html>

七、offset系列

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 300px;
            padding: 10px;
            border: 10px solid #ccc;
            margin: 10px;
            height: 100px;
            background-color: #f99;
        }
    </style>
</head>
<body>
    
    <div></div>

    <script>
        // offset系列
        // 获取大小的: offsetWidth offsetHeight

        // 需求: 获取div的宽高

        var box = document.querySelector("div");
        // style去获取宽高  -- 行内样式
        // console.log(box.style.width);  

        // offsetWidth 可以获取元素的真实的宽度
        //      内容的宽度 + padding + border
        //      返回数值,方便参与运算
        console.log(box.offsetWidth);
        console.log(box.offsetHeight);


        // 通过 offsetWidth 设置
        //  该属性是只读属性,设置无效
        // box.offsetWidth = 400;
        // box.offsetHeight = 400;


        // 如何去设置元素的宽高
        // width ==> 这样设置宽度,限制于图片,图片有width属性
        // box.width = 400;


        // 通过style 来设置行内样式
        box.style.width = "400px";
        box.style.height = "400px";


        // 小结:
        //  1. 获取元素的大小
        //      style ==> 行内样式
        //      offsetWidth 来获取元素真实的宽度
        //      
        //  2. 设置元素的大小
                // offsetWidth 是只读属性
                // style去设置width height
    </script>
</body>
</html>

1.offsetHeight与offsetWidth

在这里插入图片描述

2.offsetParent

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    
    <div class="father">
        father
        <div class="son">
            son
            <div class="sun">
                sun
            </div>
        </div>
    </div>

    <script>
        // offsetParent
        // parentNode  ==>  获取父元素

        var sun = document.querySelector(".sun");
        console.log(sun.parentNode); // son

        // 获取该元素最近的有定位的父元素,如果都没有定位,找到的是body
        console.log(sun.offsetParent); // 定位相关的

        // 小结:
        //  parentNode  找父元素,找亲爹
        //  offsetParent : 找有钱的爹
    </script>
</body>
</html>

3.offsetLeft与offsetTop

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .father{
            width: 400px;
            height: 400px;
            background-color: #f99;
            margin: 100px;
            padding-left: 100px;
            position: relative;
        }
        .son{
            width: 100px;
            height: 100px;
            position: relative;
            left: 50px;
            margin-left: 50px; 
            top: 180px;
            background-color: #ccc;
        }
    </style>
</head>
<body>
    
    <div class="father">
        <div class="son"></div>
    </div>

    <script>
        // offsetLeft与offsetTop

        var son = document.querySelector(".son");
        // style 行内
        // console.log(son.style.left);

        // offsetLeft 获取的是当前元素距离offsetparent之间的真实的距离
        console.log(son.offsetLeft);
        console.log(son.offsetTop);

        

        // 设置距离  设置无效
        // son.offsetLeft = 0;

        // 设置:
        son.style.left = "-150px";
        son.style.top = 0;


        // 小结:
        //  1. offsetLeft offsetTop  获取元素的位置信息(距离offsetParnet)
        //  2. 只能获取位置,设置无效
        //  3. style来设置行内样式

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

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        // offset系列:
        //  offsetWidth  offsetHeight  获取大小
        //  offsetParent   最近有定位的父元素
        //  offsetLeft offsetTop   获取位置信息

        // 共同点: 都是只读的
        // 设置大小。位置:
        //  style去设置 style.width  style.left

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

八、动画函数封装

1.动画初体验

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    * {
        margin: 0;
        padding: 0;
    }

    div {
        width: 100px;
        height: 100px;
        background-color: #f99;
        position: absolute;
        top: 40px;
        left: 0;
    }
    </style>
</head>

<body>
    <button>移动到400</button>
    <div></div>
    <script>
    // 需求: 点击按钮让div做动画效果移动到left为400的位置

    var btn = document.querySelector("button");
    var box = document.querySelector("div");

    // 这样是没有动画效果
    /*btn.onclick = function() {
        box.style.left = "400px";
    }*/


    // 动画效果实现的原理:
    //  在当前的位置上每次移动一段距离,不停的移动(用到定时器),就会有动画效果


    /*// 能实现移动效果,但是current 当前值固定写死了
    var current = 0; // 获取div的当前到左边的距离
    btn.onclick = function() {
        current += 10;
        box.style.left = current + "px";
    }*/


    // 点击进行移动
    /*btn.onclick = function() {
        var current = box.offsetLeft; // 获取div的当前到左边的距离
        // 每次移动10px
        current += 10;
        box.style.left = current + "px";
    }*/


    // 用定时器不停的移动
    /*btn.onclick = function() {
        setInterval(function(){
            var current = box.offsetLeft; // 获取div的当前到左边的距离
            // 每次移动10px
            current += 10;
            box.style.left = current + "px";
        }, 30)
    }*/


    // 到400就停止
    //   判断div到左边的距离
    //    距离 >= 400 ==> 停止,清除定时器
    //    距离 < 400  ==> 还没有到达终点,继续运动
    /*btn.onclick = function() {
        var timerid = setInterval(function(){
            var current = box.offsetLeft; // 获取div的当前到左边的距离
            console.log(current);
            if(current >= 400){
                // 到达终点
                clearInterval(timerid);
            }else{
                // 还没有到达
                // 每次移动10px
                current += 10;
                box.style.left = current + "px";
            }
        }, 30)
    }*/

    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;

        }
        div{
            width: 100px;
            height: 100px;
            background-color: #f99;
            position: absolute;
            top:40px;
        }
    </style>
</head>
<body>
    <button>移动去400</button>
    <div></div>

    <script>
        var btn = document.querySelector("button");
        var div = document.querySelector("div");

        btn.onclick = function () {
            var timerid = setInterval(function () {
                // 1. 每次获取div左边的距离
                var current = div.offsetLeft;

                if(current >= 400){
                    // 到终点
                    clearInterval(timerid);
                }else{
                    // 2. 在当前距离上 + 10px
                    current += 10;

                    // 3. 设置div的left 为 current
                    div.style.left = current + "px";
                }
            }, 30)
        }
    </script>
</body>
</html>

2.动画函数封装

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;

        }
        div{
            width: 100px;
            height: 100px;
            background-color: #f99;
            position: absolute;
            top:40px;
        }
    </style>
</head>
<body>
    <button>移动去400</button>
    <button>移动去800</button>
    <div></div>

    <script>
        var btn1 = document.querySelectorAll("button")[0];
        var btn2 = document.querySelectorAll("button")[1];
        var div = document.querySelector("div");

        // 去400
        btn1.onclick = function () {
            animate(div, 400);
        }


        // 去800
        btn2.onclick = function () {
            animate(div, 800)
        }

        // 把上面的代码封装成函数
        // 该函数的作用: 可以实现任何元素去任意left位置
        // 封装:把写死的值提取成参数
        function animate(element, target){
            var timerid = setInterval(function () {
                // 1. 每次获取div左边的距离
                var current = element.offsetLeft;

                if(current >= target){
                    // 到终点
                    clearInterval(timerid);
                }else{
                    // 2. 在当前距离上 + 10px
                    current += 10;

                    // 3. 设置div的left 为 current
                    element.style.left = current + "px";
                }
            }, 30)
        }
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;

        }
        div{
            width: 100px;
            height: 100px;
            background-color: #f99;
            position: absolute;
            top:40px;
        }
    </style>
</head>
<body>
    <button>移动去400</button>
    <button>移动去800</button>
    <div></div>

    <script>
        var btn1 = document.querySelectorAll("button")[0];
        var btn2 = document.querySelectorAll("button")[1];
        var div = document.querySelector("div");

        // 去400
        btn1.onclick = function () {
            animate(div, 96);
        }

        // 去800
        btn2.onclick = function () {
            animate(div, 800)
        }


        // 需求: 让div可以从左到右 , 可以从右到走往回走的效果
        //  需要改动两个地方
        //      1. 每次移动的距离都是 +10, 这是往右走的效果
        //          想要div从800 ==> 400 ,需要-10, 就可以实现往左走
                    // 根据div的移动方向去确认+10 -10的情况
                    // 往右走  10   current < target
                    // 往左走  -10  current > target
             // 2. 需要修改if判断条件,什么时候需要清除定时器,现在的写法是满足往右走的情况
             // 需要更换判断逻辑 : 还需要移动的距离 和 每次移动的距离之间的比较
             //     还需要移动的距离 ==> target - current
             //     每次移动的距离   ==> step
                // target - current >= step  ==> 还需要继续运动
                // target - current <  step   ==> 说明到达了终点, 需要清除定时器了
                //  上面的两者值的比较,比的是值的大小,和值的正负没有关系,所以,需要对齐进行去绝对值  Math.abs()


        // 把上面的代码封装成函数
        // 该函数的作用: 可以实现任何元素去任意left位置
        // 封装:把写死的值提取成参数
        function animate(element, target){
            var timerid = setInterval(function () {
                // 1. 每次获取div左边的距离
                var current = element.offsetLeft;
                var step = current < target ? 10 : -10; // 每一次移动的距离

                if(Math.abs(target - current) < Math.abs(step)){
                    // 到终点
                    clearInterval(timerid);
                }else{
                    // 2. 在当前距离上 + 10px
                    current += step;

                    // 3. 设置div的left 为 current
                    element.style.left = current + "px";
                }
            }, 30)
        }

        // 小结:让div往回走的效果
        //  1. step 的值做了处理
        //       +10   往右走   current < target
        //       -10   往左走   current > target
        //  2. 什么时候清除定时器
        //         剩下的距离 和 每次移动的距离(step)
        //         比较的是值的关系,所以需要做绝对值处理
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;

        }
        div{
            width: 100px;
            height: 100px;
            background-color: #f99;
            position: absolute;
            top:40px;
        }
    </style>
</head>
<body>
    <button>移动去400</button>
    <button>移动去800</button>
    <div></div>

    <script>
        var btn1 = document.querySelectorAll("button")[0];
        var btn2 = document.querySelectorAll("button")[1];
        var div = document.querySelector("div");

        // 去400
        btn1.onclick = function () {
            animate(div, 96);
        }

        // 去800
        btn2.onclick = function () {
            animate(div, 800)
        }


        // 需求: 让div到达终点
        //  需要改动两个地方
        //      1. 每次移动的距离都是 +10, 这是往右走的效果
        //          想要div从800 ==> 400 ,需要-10, 就可以实现往左走
                    // 根据div的移动方向去确认+10 -10的情况
                    // 往右走  10   current < target
                    // 往左走  -10  current > target
             // 2. 需要修改if判断条件,什么时候需要清除定时器,现在的写法是满足往右走的情况
             // 需要更换判断逻辑 : 还需要移动的距离 和 每次移动的距离之间的比较
             //     还需要移动的距离 ==> target - current
             //     每次移动的距离   ==> step
                // target - current >= step  ==> 还需要继续运动
                // target - current <  step   ==> 说明到达了终点, 需要清除定时器了
                //  上面的两者值的比较,比的是值的大小,和值的正负没有关系,所以,需要对齐进行去绝对值  Math.abs()


        // 把上面的代码封装成函数
        // 该函数的作用: 可以实现任何元素去任意left位置
        // 封装:把写死的值提取成参数
        function animate(element, target){
            var timerid = setInterval(function () {
                // 1. 每次获取div左边的距离
                var current = element.offsetLeft;
                var step = current < target ? 10 : -10; // 每一次移动的距离

                if(Math.abs(target - current) < Math.abs(step)){
                    // 到终点
                    clearInterval(timerid);

                    // 有可能div是没有到达终点的情况
                    // 现在需要当清除定时器的时候,div就停下来了
                    // 直接到终点,因为现在div在90的位置,直接把div设置成终点值(相当于了移动了6px)
                    element.style.left = target + "px";
                }else{
                    // 2. 在当前距离上 + 10px
                    current += step;

                    // 3. 设置div的left 为 current
                    element.style.left = current + "px";
                }
            }, 30)
        }

        // 小结:让div往回走的效果
        //  1. step 的值做了处理
        //       +10   往右走   current < target
        //       -10   往左走   current > target
        //  2. 什么时候清除定时器
        //         剩下的距离 和 每次移动的距离(step)
        //         比较的是值的关系,所以需要做绝对值处理
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;

        }
        div{
            width: 100px;
            height: 100px;
            background-color: #f99;
            position: absolute;
            top:40px;
        }
    </style>
</head>
<body>
    <button>移动去400</button>
    <button>移动去800</button>
    <div></div>

    <script>
        var btn1 = document.querySelectorAll("button")[0];
        var btn2 = document.querySelectorAll("button")[1];
        var div = document.querySelector("div");

        // 去400
        btn1.onclick = function () {
            animate(div, 96);
        }

        // 去800
        btn2.onclick = function () {
            animate(div, 800)
        }


        // 需求: 在点击800,让div去800,又点击了去96,div身上有两个定时器
        //          来回运动
        // 原理: 在开启一个定时器之前,先把之前开启的定时器给清除掉

        // var timerid; // 存储定时器的id
        // 这种写法就相当于是下面这种写法,timerid当做window对象的一个属性了
        // window.timerid;

        // 上面的timerid声明在全局,animate函数依赖了timerid 这个全局变量

        // 把上面的代码封装成函数
        // 该函数的作用: 可以实现任何元素去任意left位置
        // 封装:把写死的值提取成参数
        function animate(element, target){
            // 把timerid存储到element元素上,元素就是dom对象


            // var timerid; // undefined
            // 预解析: 变量声明提升

            // 在开启定时器之前,先清除上一次的定时器
            console.log("timerid 清除之前的id:" +  element.timerid);

            clearInterval(element.timerid);

            // 把定时器的id存储在element的dom对象上,类似于存下标
            element.timerid = setInterval(function () {
                // 1. 每次获取div左边的距离
                var current = element.offsetLeft;
                var step = current < target ? 10 : -10; // 每一次移动的距离

                if(Math.abs(target - current) < Math.abs(step)){
                    // 到终点
                    clearInterval(element.timerid);

                    // 有可能div是没有到达终点的情况
                    // 现在需要当清除定时器的时候,div就停下来了
                    // 直接到终点,因为现在div在90的位置,直接把div设置成终点值(相当于了移动了6px)
                    element.style.left = target + "px";
                }else{
                    // 2. 在当前距离上 + 10px
                    current += step;

                    // 3. 设置div的left 为 current
                    element.style.left = current + "px";
                }
            }, 30)

            console.log("timerid 开启定时器的id: " +  element.timerid);
        }

        // 小结:让div往回走的效果
        //  1. step 的值做了处理
        //       +10   往右走   current < target
        //       -10   往左走   current > target
        //  2. 什么时候清除定时器
        //         剩下的距离 和 每次移动的距离(step)
        //         比较的是值的关系,所以需要做绝对值处理
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button>开启定时器</button>
    <script>
        var btn = document.querySelector("button");

        btn.onclick = function(){
            // 定时器的id是用数值来表示,递增,id不重复
            var timerid = setInterval(function(){}, 1000);
            console.log(timerid);
        }
    </script>
</body>
</html>

九、轮播图

1.简单轮播图

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            list-style: none;
        }
        .box{
            width: 790px;
            height: 340px;
            margin: 100px auto;
            position: relative;
            overflow: hidden;
        }
        .box ul{
            width: 800%;
            height: 340px;
            position: absolute;
        }
        .box ul li{
            float: left;
        }
        .box ol{
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            bottom: 20px;
            background-color: rgba(255, 255, 255, .5);
            border-radius: 10px;
            padding: 0 5px;
        }
        .box ol li{
            width: 12px;
            height: 12px;
            background-color: #fff;
            border-radius: 50%;
            float: left;
            margin: 5px;
            cursor: pointer;
        }
        /*增加权重*/
        .box ol li.current{
            background-color: red;
        }
    </style>
</head>

<body>
    <div class="box" id="box">
        <!-- 装图片的 -->
        <ul>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/6.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/7.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/8.jpg" alt=""></a></li>
        </ul>
        <!-- 小圆点 -->
        <ol>
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ol>
    </div>
    
    <script src="../animate.js"></script>
    <script>
        // 需求: 点击小圆点:
        //      小圆点排他
        //      移动ul: 把小圆点的下标 * 一张图片的宽度,就是ul移动left的位置

        // ul的left取值问题:只能是0或者是负值,不可能取到正值(如果出现了正值,ul和box之间有了空隙)


        // 1. 找对象
        // 2. 给小圆点支持点击事件
        // 3. 小圆点排他
        // 4. 移动ul


        // 1.
        var box = document.querySelector("#box");
        var ul = box.querySelector("ul");
        // 坑: 找小圆点,一定是ol下的小圆点
        var points = box.querySelectorAll("ol li");

        // 2.
        for (var i = 0; i < points.length; i++) {
            // 给每一个小圆点添加index属性用来记录自身的下标
            points[i].index = i;
            
            // 给每一个小圆点注册点击事件
            points[i].onclick = function () {
                // 3. 
                for (var i = 0; i < points.length; i++) {
                    points[i].className = "";
                }
                this.className = "current";

                // 4.
                // 没有动画效果,坑: style去设置left,单位px别落下了
                // ul.style.left = - this.index * box.offsetWidth + "px";

                // 使用动画效果,px单位不要带上,animate函数内部做了px处理
                // 坑: 注意下,第三个参数别忘记了,表示step每一次移动的距离
                animate(ul, -this.index * box.offsetWidth, 40);
            }
        }

        // 小结:
        //  给小圆点注册click
        //  1. 排他
        //  2. 移动ul  animate 做了处理,step参数

    </script>
</body>

</html>

2.左右焦点图

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            list-style: none;
        }
        .box{
            width: 790px;
            height: 340px;
            margin: 100px auto;
            position: relative;
            overflow: hidden;
        }
        .box ul{
            width: 800%;
            height: 340px;
            position: absolute;
        }
        .box ul li{
            float: left;
        }
        .box ol{
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            bottom: 20px;
            background-color: rgba(255, 255, 255, .5);
            border-radius: 10px;
            padding: 0 5px;
        }
        .box ol li{
            width: 12px;
            height: 12px;
            background-color: #fff;
            border-radius: 50%;
            float: left;
            margin: 5px;
            cursor: pointer;
        }
        /*增加权重*/
        .box ol li.current{
            background-color: red;
        }

        /*左右箭头*/
        .box .arrow{
            display: none;
        }
        .box:hover .arrow{
            display: block;
        }
        .box .arrow span{
            width: 30px;
            height: 60px;
            line-height: 60px;
            text-align: center;
            background-color: rgba(0,0,0,.6);
            color: #fff;
            font-size: 24px;
            cursor: pointer;
            font-family: "宋体";
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
        }
        .box .arrow span.prev{
            left: 0;
        }
        .box .arrow span.next{
            right: 0;
        }
    </style>
</head>

<body>
    <div class="box" id="box">
        <!-- 装图片的 -->
        <ul>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/6.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/7.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/8.jpg" alt=""></a></li>
        </ul>
        <!-- 小圆点 -->
        <ol>
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ol>
        <!-- 左右箭头 -->
        <div class="arrow">
            <span class="prev">&lt;</span>
            <span class="next">&gt;</span>
        </div>
    </div>
    
    <script src="../animate.js"></script>
    <script>
        // 需求: 点击小圆点:
        //      小圆点排他
        //      移动ul: 把小圆点的下标 * 一张图片的宽度,就是ul移动left的位置

        // ul的left取值问题:只能是0或者是负值,不可能取到正值(如果出现了正值,ul和box之间有了空隙)


        // 1. 找对象
        // 2. 给小圆点支持点击事件
        // 3. 小圆点排他
        // 4. 移动ul


        // 1.
        var box = document.querySelector("#box");
        var ul = box.querySelector("ul");
        // 坑: 找小圆点,一定是ol下的小圆点
        var points = box.querySelectorAll("ol li");

        // 2.
        for (var i = 0; i < points.length; i++) {
            // 给每一个小圆点添加index属性用来记录自身的下标
            points[i].index = i;
            
            // 给每一个小圆点注册点击事件
            points[i].onclick = function () {
                // 3. 
                for (var i = 0; i < points.length; i++) {
                    points[i].className = "";
                }
                this.className = "current";

                // 4.
                // 没有动画效果,坑: style去设置left,单位px别落下了
                // ul.style.left = - this.index * box.offsetWidth + "px";

                // 使用动画效果,px单位不要带上,animate函数内部做了px处理
                // 坑: 注意下,第三个参数别忘记了,表示step每一次移动的距离
                animate(ul, -this.index * box.offsetWidth, 40);
            }
        }


        

        

        // 小结:
        //  给小圆点注册click
        //  1. 排他
        //  2. 移动ul  animate 做了处理,step参数

    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        *{
            margin: 0;
            padding: 0;
            list-style: none;
        }
        .box{
            width: 790px;
            height: 340px;
            margin: 100px auto;
            position: relative;
            overflow: hidden;
        }
        .box ul{
            width: 800%;
            height: 340px;
            position: absolute;
        }
        .box ul li{
            float: left;
        }
        .box ol{
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            bottom: 20px;
            background-color: rgba(255, 255, 255, .5);
            border-radius: 10px;
            padding: 0 5px;
        }
        .box ol li{
            width: 12px;
            height: 12px;
            background-color: #fff;
            border-radius: 50%;
            float: left;
            margin: 5px;
            cursor: pointer;
        }
        /*增加权重*/
        .box ol li.current{
            background-color: red;
        }

        /*左右箭头*/
        .box .arrow{
            display: none;
        }
        .box:hover .arrow{
            display: block;
        }
        .box .arrow span{
            width: 30px;
            height: 60px;
            line-height: 60px;
            text-align: center;
            background-color: rgba(0,0,0,.6);
            color: #fff;
            font-size: 24px;
            cursor: pointer;
            font-family: "宋体";
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
        }
        .box .arrow span.prev{
            left: 0;
        }
        .box .arrow span.next{
            right: 0;
        }
    </style>
</head>

<body>
    <div class="box" id="box">
        <!-- 装图片的 -->
        <ul>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/6.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/7.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/8.jpg" alt=""></a></li>
        </ul>
        <!-- 小圆点 -->
        <ol>
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ol>
        <!-- 左右箭头 -->
        <div class="arrow">
            <span class="prev">&lt;</span>
            <span class="next">&gt;</span>
        </div>
    </div>
    
    <script src="../animate.js"></script>
    <script>
        // 需求: 点击小圆点:
        //      小圆点排他
        //      移动ul: 把小圆点的下标 * 一张图片的宽度,就是ul移动left的位置

        // ul的left取值问题:只能是0或者是负值,不可能取到正值(如果出现了正值,ul和box之间有了空隙)

        // 1. 找对象
        // 2. 给小圆点支持点击事件
        // 3. 小圆点排他
        // 4. 移动ul

        // 1.
        var box = document.querySelector("#box");
        var ul = box.querySelector("ul");
        var imgs = ul.children;  // li
        var nextBtn = box.querySelector(".arrow .next");
        var prevBtn = box.querySelector(".arrow .prev");
        var index = 0; // 当前展示的图片的下标,默认值为0,默认是展示第一张

        // 右箭头的点击事件
        // 思路: 
        //  1. 找对象
        //  2. 给右箭头注册click
        //  3. index++
        //  4. 移动ul, ul的left = -index * box的宽度


        // 需求: 当点击右箭头的时候,如果当前展示的图片是最后一张的时候,此次点击右箭头没有任何反应

        // 2.
        nextBtn.onclick = function(){
            if(index >= imgs.length - 1){
                // 此时展示的就是最后一张
                return;
            }

            // 3.
            index++;
            // 4.
            animate(ul, -index * box.offsetWidth, 40);
        }
        
        // 左箭头和右箭头的事件处理类似,不同的是 index--
        prevBtn.onclick = function () {
            if(index <= 0){
                // 此时展示的就是第一张
                return;
            }

            index--;
            animate(ul, -index * box.offsetWidth, 40);
        }


        // 小结:
        //  1. 右箭头: 点击的时候,切换下一张
        //        var index = 0; // 当前展示的图片的下标
        //        点击的时候。index++,移动ul
        //        ul的left = -index * box的宽度

        // 重点: index

    </script>
</body>

</html>

3.无缝轮播图

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .box {
        width: 790px;
        height: 340px;
        margin: 100px auto;
        position: relative;
        overflow: hidden;
    }

    .box ul {
        /*坑: 一定要把ul的宽度变大,能够放下所有的图片,尤其是假图片*/
        width: 900%;
        height: 340px;
        position: absolute;
    }

    .box ul li {
        float: left;
    }

    .box ol {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        bottom: 20px;
        background-color: rgba(255, 255, 255, .5);
        border-radius: 10px;
        padding: 0 5px;
    }

    .box ol li {
        width: 12px;
        height: 12px;
        background-color: #fff;
        border-radius: 50%;
        float: left;
        margin: 5px;
        cursor: pointer;
    }

    /*增加权重*/
    .box ol li.current {
        background-color: red;
    }

    /*左右箭头*/
    .box .arrow {
        display: none;
    }

    .box:hover .arrow {
        display: block;
    }

    .box .arrow span {
        width: 30px;
        height: 60px;
        line-height: 60px;
        text-align: center;
        background-color: rgba(0, 0, 0, .6);
        color: #fff;
        font-size: 24px;
        cursor: pointer;
        font-family: "宋体";
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
    }

    .box .arrow span.prev {
        left: 0;
    }

    .box .arrow span.next {
        right: 0;
    }
    </style>
</head>

<body>
    <div class="box" id="box">
        <!-- 装图片的 -->
        <ul>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/6.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/7.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/8.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
        </ul>
        <!-- 小圆点 -->
        <ol>
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ol>
        <!-- 左右箭头 -->
        <div class="arrow">
            <span class="prev">&lt;</span>
            <span class="next">&gt;</span>
        </div>
    </div>
    <script src="../animate.js"></script>
    <script>
    // 需求: 点击小圆点:
    //      小圆点排他
    //      移动ul: 把小圆点的下标 * 一张图片的宽度,就是ul移动left的位置

    // ul的left取值问题:只能是0或者是负值,不可能取到正值(如果出现了正值,ul和box之间有了空隙)

    // 1. 找对象
    // 2. 给小圆点支持点击事件
    // 3. 小圆点排他
    // 4. 移动ul

    // 1.
    var box = document.querySelector("#box");
    var ul = box.querySelector("ul");
    var imgs = ul.children; // li
    var nextBtn = box.querySelector(".arrow .next");
    var prevBtn = box.querySelector(".arrow .prev");
    var index = 0; // 当前展示的图片的下标,默认值为0,默认是展示第一张

    // 右箭头的点击事件
    // 思路: 
    //  1. 找对象
    //  2. 给右箭头注册click
    //  3. index++
    //  4. 移动ul, ul的left = -index * box的宽度


    // 需求: 点击右箭头实现无缝效果
    // 实现原理: 
    //     1. 把第一张复制一份,添加到最后一张的后面,复制的第一张图片(假图片)
    //          坑: ul的样式width别忘记了改大
    //     2. 点击右箭头的时候,判断此时展示的是否是最后一张(假图片)
    //     3. 首先让ul瞬间移动到left 为0的位置(展示的就是第一张,没有动画效果)
    //              index = 0;
    //     4. index++, index = 1,展示的就是第二张




    // 2.
    nextBtn.onclick = function() {
        if (index >= imgs.length - 1) {
            // 此时展示的就是最后一张(假图片)

            // index = -1; // 这样index = -1,下面index++,index = 0,这样的效果是往回走的效果。

            // 瞬间切换到第一张
            // ul 的left = 0;

            // 这种做法(没有假图片的情况),是可以从最后一张回到第一张,但是存在了问题: 最后一张到第一张没有动画效果。
            // index = 0; // 表示当前展示的图片,第一张
            // ul.style.left = 0;


            // 坑:不仅要把ul的left变成0的位置,还需要把下标变成0,以为后面index++,需要从0的基础上++,那这样展示的就是第二张了
            index = 0; // 展示的就是第一张
            ul.style.left = 0; // 瞬间回到第一张
        }

        // 3.
        index++;
        // 4.
        animate(ul, -index * box.offsetWidth, 40);
    }

    // 左箭头和右箭头的事件处理类似,不同的是 index--
    prevBtn.onclick = function() {
        if (index <= 0) {
            // 此时展示的就是第一张
                
            // 首先index = 8, 是假图片的下标,瞬间跳转到假图片
            // 然后从假图片切换到上一张
            index = imgs.length - 1;
            ul.style.left = -index * box.offsetWidth + "px";

        }

        index--;
        animate(ul, -index * box.offsetWidth, 40);
    }


    // 小结:
    //  1. 右箭头: 点击的时候,切换下一张
    //        var index = 0; // 当前展示的图片的下标
    //        点击的时候。index++,移动ul
    //        ul的left = -index * box的宽度

    // 重点: index
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .box {
        width: 790px;
        height: 340px;
        margin: 100px auto;
        position: relative;
        overflow: hidden;
    }

    .box ul {
        /*坑: 一定要把ul的宽度变大,能够放下所有的图片,尤其是假图片*/
        width: 900%;
        height: 340px;
        position: absolute;
    }

    .box ul li {
        float: left;
    }

    .box ol {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        bottom: 20px;
        background-color: rgba(255, 255, 255, .5);
        border-radius: 10px;
        padding: 0 5px;
    }

    .box ol li {
        width: 12px;
        height: 12px;
        background-color: #fff;
        border-radius: 50%;
        float: left;
        margin: 5px;
        cursor: pointer;
    }

    /*增加权重*/
    .box ol li.current {
        background-color: red;
    }

    /*左右箭头*/
    .box .arrow {
        display: none;
    }

    .box:hover .arrow {
        display: block;
    }

    .box .arrow span {
        width: 30px;
        height: 60px;
        line-height: 60px;
        text-align: center;
        background-color: rgba(0, 0, 0, .6);
        color: #fff;
        font-size: 24px;
        cursor: pointer;
        font-family: "宋体";
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
    }

    .box .arrow span.prev {
        left: 0;
    }

    .box .arrow span.next {
        right: 0;
    }
    </style>
</head>

<body>
    <div class="box" id="box">
        <!-- 装图片的 -->
        <ul>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/6.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/7.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/8.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
        </ul>
        <!-- 小圆点 -->
        <ol>
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ol>
        <!-- 左右箭头 -->
        <div class="arrow">
            <span class="prev">&lt;</span>
            <span class="next">&gt;</span>
        </div>
    </div>
    <script src="../animate.js"></script>
    <script>
    // 需求: 点击小圆点:
    //      小圆点排他
    //      移动ul: 把小圆点的下标 * 一张图片的宽度,就是ul移动left的位置

    // ul的left取值问题:只能是0或者是负值,不可能取到正值(如果出现了正值,ul和box之间有了空隙)

    // 1. 找对象
    // 2. 给小圆点支持点击事件
    // 3. 小圆点排他
    // 4. 移动ul

    // 1.
    var box = document.querySelector("#box");
    var ul = box.querySelector("ul");
    var imgs = ul.children; // li
    var points = box.querySelectorAll("ol li");
    var nextBtn = box.querySelector(".arrow .next");
    var prevBtn = box.querySelector(".arrow .prev");
    var index = 0; // 当前展示的图片的下标,默认值为0,默认是展示第一张

    // 右箭头的点击事件
    // 思路: 
    //  1. 找对象
    //  2. 给右箭头注册click
    //  3. index++
    //  4. 移动ul, ul的left = -index * box的宽度


    // 需求: 点击左右箭头,同步小圆点排他




    // 2.
    nextBtn.onclick = function() {
        if (index >= imgs.length - 1) {
            // 此时展示的就是最后一张(假图片)

            // index = -1; // 这样index = -1,下面index++,index = 0,这样的效果是往回走的效果。

            // 瞬间切换到第一张
            // ul 的left = 0;

            // 这种做法(没有假图片的情况),是可以从最后一张回到第一张,但是存在了问题: 最后一张到第一张没有动画效果。
            // index = 0; // 表示当前展示的图片,第一张
            // ul.style.left = 0;


            // 坑:不仅要把ul的left变成0的位置,还需要把下标变成0,以为后面index++,需要从0的基础上++,那这样展示的就是第二张了
            index = 0; // 展示的就是第一张
            ul.style.left = 0; // 瞬间回到第一张
        }

        // 3.
        index++;
        // 4.
        animate(ul, -index * box.offsetWidth, 40);


        // 同步小圆点
        for (var i = 0; i < points.length; i++) {
            points[i].className = "";
        }
        // 复活我自己 -- 找到对应下标的小圆点,添加current类名
        // this ==> prevBtn

        // 判断index的情况,因为图片的个数是9,小圆点的个数为8,当展示最后一张图片的时候,index是8,小圆点没有下标为8的那个圆点
        if(index >= 8){
            // 此时展示的是假图片,对于用户来说,看到的效果是展示了第一张,就需要让第一个小圆点高亮
            points[0].className = "current";
        }else{
            // 0 - 7
            points[index].className = "current";
        }
    }

    // 左箭头和右箭头的事件处理类似,不同的是 index--
    prevBtn.onclick = function() {
        if (index <= 0) {
            // 此时展示的就是第一张
                
            // 首先index = 8, 是假图片的下标,瞬间跳转到假图片
            // 然后从假图片切换到上一张
            index = imgs.length - 1;
            ul.style.left = -index * box.offsetWidth + "px";
        }

        index--;
        animate(ul, -index * box.offsetWidth, 40);

        // 同步小圆点
        for (var i = 0; i < points.length; i++) {
            points[i].className = "";
        }
        // 复活我自己 -- 找到对应下标的小圆点,添加current类名
        // this ==> prevBtn
        console.log("index " + index);
        points[index].className = "current";
    }


    // 小结:
    //  1. 右箭头: 点击的时候,切换下一张
    //        var index = 0; // 当前展示的图片的下标
    //        点击的时候。index++,移动ul
    //        ul的left = -index * box的宽度

    // 重点: index
    </script>
</body>

</html>

4.完整版轮播图

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .box {
        width: 790px;
        height: 340px;
        margin: 100px auto;
        position: relative;
        overflow: hidden;
    }

    .box ul {
        /*坑: 一定要把ul的宽度变大,能够放下所有的图片,尤其是假图片*/
        width: 900%;
        height: 340px;
        position: absolute;
    }

    .box ul li {
        float: left;
    }

    .box ol {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        bottom: 20px;
        background-color: rgba(255, 255, 255, .5);
        border-radius: 10px;
        padding: 0 5px;
    }

    .box ol li {
        width: 12px;
        height: 12px;
        background-color: #fff;
        border-radius: 50%;
        float: left;
        margin: 5px;
        cursor: pointer;
    }

    /*增加权重*/
    .box ol li.current {
        background-color: red;
    }

    /*左右箭头*/
    .box .arrow {
        display: none;
    }

    .box:hover .arrow {
        display: block;
    }

    .box .arrow span {
        width: 30px;
        height: 60px;
        line-height: 60px;
        text-align: center;
        background-color: rgba(0, 0, 0, .6);
        color: #fff;
        font-size: 24px;
        cursor: pointer;
        font-family: "宋体";
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
    }

    .box .arrow span.prev {
        left: 0;
    }

    .box .arrow span.next {
        right: 0;
    }
    </style>
</head>

<body>
    <div class="box" id="box">
        <!-- 装图片的 -->
        <ul>
            <li><a href="#"><img src="images/1.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/2.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/3.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/4.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/5.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/6.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/7.jpg" alt=""></a></li>
            <li><a href="#"><img src="images/8.jpg" alt=""></a></li>
        </ul>
        <!-- 小圆点 -->
        <ol></ol>
        <!-- 左右箭头 -->
        <div class="arrow">
            <span class="prev">&lt;</span>
            <span class="next">&gt;</span>
        </div>
    </div>
    <script src="../animate.js"></script>
    <script>
    // 需求: 
    // 1. js动态添加小圆点
    // 2. js动态添加最后一张假图片
    // 3. 实现左右焦点图 + 无缝滚动 + 同步小圆点
    // 4. 自动播放
    // 5. 点击小圆点同步切换
    // 6. 解决点击小圆点的bug(展示最后一张假图片的时候,点击小圆点)


    // 实现第一个和第二个需求: 
    //  做了两件修改代码的事情: 
    //      1. 假图片去掉
    //      2. 小圆点的li都删除了


    // 1.
    var box = document.querySelector("#box");
    var ul = box.querySelector("ul");
    var imgs = ul.children; // li
    var ol = box.querySelector("ol");
    var nextBtn = box.querySelector(".arrow .next");
    var prevBtn = box.querySelector(".arrow .prev");
    var index = 0; // 当前展示的图片的下标,默认值为0,默认是展示第一张


    // 功能1. js动态添加小圆点
    //  根据图片的个数去创建小圆点
    //  1. for循环
    //  2. 每循环一次,创建一个li
    //  3. 添加到ol中
    //  4. 第一个小圆点高亮, current类名

    for (var i = 0; i < imgs.length; i++) {
        // 2.
        var li = document.createElement("li");
        // 3.
        ol.appendChild(li);
    }
    // 4.
    // 从ol中获取所有的小圆点
    var points = ol.children;
    // 拿第一个小圆点添加类名
    points[0].className = "current";



    // 功能2: js动态添加最后一张假图片
    ul.appendChild(ul.firstElementChild.cloneNode(true));


    // 功能3: 同步小圆点 + 左右 + 无缝
    nextBtn.onclick = function() {
        if (index >= imgs.length - 1) {
            // 此时展示的就是最后一张(假图片)

            // 坑:不仅要把ul的left变成0的位置,还需要把下标变成0,以为后面index++,需要从0的基础上++,那这样展示的就是第二张了
            index = 0; // 展示的就是第一张
            ul.style.left = 0; // 瞬间回到第一张
        }

        // 3.
        index++;
        // 4.
        animate(ul, -index * box.offsetWidth, 40);


        // 同步小圆点
        for (var i = 0; i < points.length; i++) {
            points[i].className = "";
        }
        // 复活我自己 -- 找到对应下标的小圆点,添加current类名
        // this ==> prevBtn

        // 判断index的情况,因为图片的个数是9,小圆点的个数为8,当展示最后一张图片的时候,index是8,小圆点没有下标为8的那个圆点
        if(index >= 8){
            // 此时展示的是假图片,对于用户来说,看到的效果是展示了第一张,就需要让第一个小圆点高亮
            points[0].className = "current";
        }else{
            // 0 - 7
            points[index].className = "current";
        }
    }

    // 左箭头和右箭头的事件处理类似,不同的是 index--
    prevBtn.onclick = function() {
        if (index <= 0) {
            // 此时展示的就是第一张
                
            // 首先index = 8, 是假图片的下标,瞬间跳转到假图片
            // 然后从假图片切换到上一张
            index = imgs.length - 1;
            ul.style.left = -index * box.offsetWidth + "px";
        }

        index--;
        animate(ul, -index * box.offsetWidth, 40);

        // 同步小圆点
        for (var i = 0; i < points.length; i++) {
            points[i].className = "";
        }
        // 复活我自己 -- 找到对应下标的小圆点,添加current类名
        // this ==> prevBtn
        console.log("index " + index);
        points[index].className = "current";
    }



    // 功能4: 自动播放
    var timerid = setInterval(function(){
        // 切换下一张
        nextBtn.onclick();  // 把右箭头的点击事件给主动调用了
    }, 2000)

    // 鼠标移入到box上,清除定时器
    box.onmouseover = function () {
        clearInterval(timerid)
    }

    // 鼠标离开box的时候,继续开启定时器,触发右箭头的点击事件
    box.onmouseout = function () {
        // 坑: timerid 前面千万不要加var
        //      否则,移入移出box,box会越来越快
        timerid = setInterval(function(){
            nextBtn.onclick();  // 把右箭头的点击事件给主动调用了
        }, 2000)
    }



    // 功能5: 点击小圆点同步切换
    //  思路: 
    //   1. 给所有的小圆点注册click
    //   2. 排他
    //   3. 移动ul到对应下标的图片


    // 解决的问题: 当展示最后的假图片的时候,如果点击了小圆点,倒着往回走切换到对应的小圆点的图片
    //   解决办法: 当点击的时候,如果当前展示的是假图片,瞬间切换到第一张
    //          从第一张顺着切换到小圆点对应的哪一张

    // 1.
    for (var i = 0; i < points.length; i++) {
        points[i].index = i; // 添加下标
        points[i].onclick = function () {
            // 2.
            for (var i = 0; i < points.length; i++) {
                points[i].className = "";
            }
            this.className = "current";

            // 判断
            if(index >= imgs.length - 1){
                // 展示的是假图片
                ul.style.left = 0;
                index = 0; // index 等于0, 写不写无所谓,因为下面的代码立即把index同步为小圆点的下标。
            }


            // 3.
            // 坑: index得维护
            index = this.index;  // 同步index值为小圆点的下标
            animate(ul, -this.index * box.offsetWidth, 40);
        }
    }



    </script>
</body>

</html>

十、&&和||的短路问题

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        // console.log(true && false);  // false
        // console.log(true && true); // true
        // console.log(null && undefined);  // null 
        // console.log("abc" && "def"); // "def")


        // 逻辑与 逻辑或  ==> 短路运算符
        // && : 从左到右进行运算, 如果遇到了假值(布尔类型为false的值),逻辑就中断了,后面的代码就不执行了。返回这个假值(值本身)。如果没有假值,就返回最后一个真值。


        // 逻辑与的使用场景
        function foo(fn){
            // 没有实参,形参的值就是undefined

            // console.log(fn);  // 是个函数

            // fn 没有接受到实参的时候, fn是个undefined,fn && fn();找假值,找到的就时fn,后面的代码几句中断了不执行了,fn()没有调用了
            fn && fn();

            /*if(fn){
                fn();
            }*/

        }
        // 当fn没有实参的时候,foo内部调用了fn(), 就会报错了
        // 当传递了函数就执行函数,没有传递,不能报错
        // foo(   function(){console.log(123);}    );
        foo(  );


        // 逻辑与: 从左到右,找假值,返回假值(不是返回false)。
        //          使用场景: 只有在fn被传递了函数的时候,才会执行fn函数
        //                  如果fn参数没有传递,fn是undefined,false,逻辑就中断了,fn()就不会被执行了,避免了报错



        // 逻辑或  ||
        // 从左到右进行运算, 如果遇到了真值(布尔类型为true的值),逻辑就中断了,后面的代码就不执行了。返回这个真值(值本身)。如果没有真值,就返回最后一个假值。


        // 假值: 0 false "" NaN undefined null  
        // 除了这6个,其他的值都是真值。

        // console.log( 0 || "" || [] || {} );  // []
        // console.log("abc" || [1] || undefined || 123);  // "abc"



        // 逻辑或的使用场景
        //  1. 兼容性处理
        //  2. 给函数的参数设置默认值

        function sum(n){
            // 默认值: 如果没有传递参数,n就会取到默认值,但是如果有传递参数,n取到的是传递的参数
            n = n || 10; // 这是给参数n设置默认值10

            console.log(n + 10);
        }
        sum(30);


        // 小结:
        //  1. && 假值  返回假值
        //  2. || 真值  返回真值
        //         2.1 兼容性处理
        //         2.2 给函数的参数设置默认值

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

十一、缓动框架

1.缓动函数初体验 - 让div做缓动动画去400

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        div{
            position: absolute;
            top: 40px;
            width: 100px;
            height: 100px;
            background-color: #f99;
        }
    </style>
</head>
<body>
    <button>400</button>
    <div></div>

    <script>
        // 缓动函数初体验 , 基于运算的动画

        // 缓动函数 ==> 每次移动的距离是能够变化的
        // 公式: var step = (target - current)/10;

        // 先实现移动, 匀速的,每次移动的距离是固定

        var btn = document.querySelector("button");
        var box = document.querySelector("div");

        btn.onclick = function () {
            var timerid = setInterval(function(){
                // 1. 首先获取div的到左边的距离
                var current = box.offsetLeft;

                // 2. 来一个终点值 
                var target = 400;

                // 3. 每次在当前位置上移动一段距离
                var step = (target - current)/10;

                // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
                //  保证让step 每次移动的距离是1px,肯定能够移动到终点
                step = Math.ceil(step);

                console.log(step);

                current += step;
                box.style.left = current + "px";


                if(current == target){
                    // 由于最后是1px1px移动到终点,所以current 肯定能等于target

                    // 到终点了,清除定时器
                    clearInterval(timerid)
                }
            }, 30)
        }

        // 缓动动画实现了,step的值是在发生改变的
        //  遇到的问题: 
        //      box停下了,但是没有到达终点

        // 原因: offsetLeft在获取值的时候,把小数部分的值给丢了
        // 解决: 让step每一次移动的距离最小值就是1,这样就解决了没有小数部分的问题



        // 小结:
        //  offsetLeft 取值存在问题,小数部分丢失
        //  解决办法: 对step向上取整。step最小值就是1px
    </script>
</body>
</html>

2.缓动函数-让div到达终点清除定时器

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        div{
            position: absolute;
            top: 40px;
            width: 100px;
            height: 100px;
            background-color: #f99;
        }
    </style>
</head>
<body>
    <button>400</button>
    <button>800</button>
    <div></div>

    <script>
        // 缓动函数初体验 , 基于运算的动画

        // 缓动函数 ==> 每次移动的距离是能够变化的
        // 公式: var step = (target - current)/10;

        // 先实现移动, 匀速的,每次移动的距离是固定

        var btn1 = document.querySelectorAll("button")[0];
        var btn2 = document.querySelectorAll("button")[1];
        var box = document.querySelector("div");

        btn1.onclick = function () {
            animate(box, 400)
        }


        btn2.onclick = function () {
            animate(box, 800)
        }

        // 封装
        // 把写死的值提取出来做参数
        function animate(element, target){
            clearInterval(element.timerid)

            element.timerid = setInterval(function(){
                // 1. 首先获取div的到左边的距离
                var current = element.offsetLeft;

                // 2. 来一个终点值 ,通过参数来传递

                // 3. 每次在当前位置上移动一段距离
                var step = (target - current)/10;

                // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
                //  保证让step 每次移动的距离是1px,肯定能够移动到终点
                step = Math.ceil(step);

                console.log(step);

                current += step;
                element.style.left = current + "px";

                if(current == target){
                    // 由于最后是1px1px移动到终点,所以current 肯定能等于target
                    // 到终点了,清除定时器
                    clearInterval(element.timerid);
                }
            }, 30)
        }


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

3.缓动函数–让div做多个动画效果

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        div{
            position: absolute;
            top: 40px;
            width: 100px;
            height: 100px;
            background-color: #f99;
            border-radius: 10px;
        }
    </style>
</head>
<body>
    <button>400</button>
    <button>800</button>
    <div></div>

    <script>
        // 需求: 让div 800 ==> 400
        // 问题: step -0.9  Math.ceil(step) ==> 0
        // 解决: 让step向下取整,让step最小值是1,(-1),往左走的效果

        // 说明step需要向上和向下取整
        //  step > 0  ,说明移动到右边去, step 向上取整  +1
        //  step < 0  ,说明移动到左边去, step 向下取整  -1



        var btn1 = document.querySelectorAll("button")[0];
        var btn2 = document.querySelectorAll("button")[1];
        var box = document.querySelector("div");

        btn1.onclick = function () {
            animate(box, 400)
        }


        btn2.onclick = function () {
            animate(box, 800)
        }

        // 封装
        // 把写死的值提取出来做参数
        function animate(element, target){
            clearInterval(element.timerid)

            element.timerid = setInterval(function(){
                // 1. 首先获取div的到左边的距离
                // var current = element.offsetLeft;

                // 没有这个属性
                var current = element.offsetBorderRadius;
                console.log(current);

                // 2. 来一个终点值 ,通过参数来传递

                // 3. 每次在当前位置上移动一段距离
                var step = (target - current)/10;

                // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
                //  保证让step 每次移动的距离是1px,肯定能够移动到终点
                step = step > 0 ? Math.ceil(step) : Math.floor(step);

                console.log(step);

                current += step;
                element.style.left = current + "px";

                if(current == target){
                    // 由于最后是1px1px移动到终点,所以current 肯定能等于target
                    // 到终点了,清除定时器
                    clearInterval(element.timerid);
                }
            }, 30)
        }

        // 小结: 
        //  800 去400, 没有到达终点   409 
        //  原因: step  -0.9  -0  想要的setp是-1
        //  解决办法: 对step做向下取整
        //  最终: 对step做判断  往右走, step最小值 +1
        //                  往左走, step最小值 -1

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

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

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
    * {
        margin: 0;
        padding: 0
    }

    ul {
        list-style: none
    }

    body {
        background-color: #333;
    }

    .nav {
        width: 800px;
        height: 42px;
        margin: 100px auto;
        background: url(images/rss.png) right center no-repeat;
        background-color: #fff;
        border-radius: 10px;
        position: relative;
    }

    .nav li {
        width: 83px;
        height: 42px;
        text-align: center;
        line-height: 42px;
        float: left;
        cursor: pointer;
    }

    .nav span {
        position: absolute;
        top: 0;
        left: 0;
        width: 83px;
        height: 42px;
        background: url(images/cloud.gif) no-repeat;
    }

    ul {
        position: relative;
    }
    </style>
</head>

<body>
    <div class="nav">
        <span id="cloud"></span>
        <ul id="navBar">
            <li>北京校区</li>
            <li>上海校区</li>
            <li>广州校区</li>
            <li>深圳校区</li>
            <li>武汉校区</li>
            <li>关于我们</li>
            <li>联系我们</li>
            <li>招贤纳士</li>
        </ul>
    </div>


    <script>
    // 实现功能: 
    //  1. 鼠标移入 云朵跟随效果
    //  2. 鼠标离开 回到原来的位置
    //  3. 鼠标点击 修改云朵回去的位置


    // 功能1: 
    //  思路思路: 
    //  1. 获取所有的导航li
    //  2. 给li注册mouseover
    //  3. 需要让span移动, 移动的值就是当前li的到左边的距离


    // 功能2: 
    //  思路:
    //   1. 给li注册mouseout
    //   2. 让span移动到0的位置


    // 功能3: 
    //  思路: 
    //    1. 给li注册click
    //    2. 把变量position的值修改成当前li的offsetLeft


    // 1.
    var lis = document.querySelectorAll("#navBar li");
    var cloud = document.querySelector("#cloud");

    var position = 0; // 表示鼠标离开的时候,span回去的位置


    // 2.
    for (var i = 0; i < lis.length; i++) {

        // 这是鼠标移入事件
        lis[i].onmouseover = function() {
            // 3,
            animate(cloud, this.offsetLeft);
        }

        // 这是鼠标离开事件
        lis[i].onmouseout = function() {
            animate(cloud, position);
        }

        // 注册click
        lis[i].onclick = function() {
            position = this.offsetLeft;
        }
    }

    function animate(element, target) {
        clearInterval(element.timerid)
        element.timerid = setInterval(function() {
            var current = element.offsetLeft;
            var step = (target - current) / 5;
            step = step > 0 ? Math.ceil(step) : Math.floor(step);

            current += step;
            element.style.left = current + "px";

            if (current == target) {
                clearInterval(element.timerid);
            }
        }, 30)
    }

    // 小结:
    // 点击事件,把当前点击的li的offsetLeft获取到,赋值给 position
    // 然后鼠标离开的时候,回去的位置,回到position
    </script>
</body>

</html>

4.获取计算后的样式

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #f99;
            border-radius: 10px;
        }

        .box{
            border-radius: 20px;
        }
    </style>
</head>
<body>
    <div class="box">123</div>

    <script>
        // 需求: 获取div的圆角值多少

        // style 去获取,  操作是行内样式

        var div = document.querySelector("div");
        // console.log(div.style.borderRadius);

        // offset系列: 宽高  位置


        // 获取计算后的样式, 理解: 就是真正在元素上起效果的样式
        // 语法: window.getComputedStyle(元素,伪类);
        //  元素: 表示获取那个元素计算后的样式
        //  伪类: 表示获取元素伪类的样式,但是通常不需要,通常写null
        //  返回值: 返回了对象,对象里面就有元素所有计算后的样式

        // var ret = window.getComputedStyle(div, null).borderRadius;
        // var ret = window.getComputedStyle(div, null).backgroundColor;
        // console.log(ret);


        // 使用建议: 对于复合样式,如果需要获取具体的样式,就写上具体的样式名,因为这样能够兼容更多的浏览器。


        // 存在兼容性问题: 
        //  IE678不支持该方法
        // console.log(div.currentStyle.backgroundColor);
        // console.log(div.currentStyle["backgroundColor"]);


        // 小结:
        //   获取样式:
        //    style来获取, 行内样式
        //   获取特殊的样式:
        //    offset系列
        //   window.getComputedStyle  获取的是计算后的样式
                // 返回值:对象


        // 获取div的字体大小
        console.log(window.getComputedStyle(div, null)["fontSize"]);
    </script>
</body>
</html>

5.缓动函数-让div可以做任意样式动画

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    * {
        padding: 0;
        margin: 0;
    }

    div {
        position: absolute;
        top: 40px;
        width: 200px;
        height: 200px;
        background-color: #f99;
        border-radius: 10px;
    }
    </style>
</head>

<body>
    <button>50</button>
    <button>100</button>
    <div></div>
    <script>
    // 需求: 让div 800 ==> 400
    // 问题: step -0.9  Math.ceil(step) ==> 0
    // 解决: 让step向下取整,让step最小值是1,(-1),往左走的效果

    // 说明step需要向上和向下取整
    //  step > 0  ,说明移动到右边去, step 向上取整  +1
    //  step < 0  ,说明移动到左边去, step 向下取整  -1

    var btn1 = document.querySelectorAll("button")[0];
    var btn2 = document.querySelectorAll("button")[1];
    var box = document.querySelector("div");

    btn1.onclick = function() {
        animate(box, "width", 300)
    }

    btn2.onclick = function() {
        animate(box, "left", 300)
    }

    // 封装
    // 把写死的值提取出来做参数
    // 参数: 
    //  element 做动画的元素
    //  attr  做动画的样式
    //  target  目标值
    function animate(element, attr, target) {
        clearInterval(element.timerid)

        element.timerid = setInterval(function() {
            // 1. 首先获取div当前的attr参数对应的样式
            // var current = element.offsetLeft;
            var current = window.getComputedStyle(element, null)[attr];

            // 坑: current是带了单位,不方便下面计算
            // 所以需要去掉px
            current = parseInt(current);


            // 2. 来一个终点值 ,通过参数来传递

            // 3. 每次在当前位置上移动一段距离
            var step = (target - current) / 10;

            // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
            //  保证让step 每次移动的距离是1px,肯定能够移动到终点
            step = step > 0 ? Math.ceil(step) : Math.floor(step);

            current += step;
            element.style[attr] = current + "px";

            if (current == target) {
                // 由于最后是1px1px移动到终点,所以current 肯定能等于target
                // 到终点了,清除定时器
                clearInterval(element.timerid);
            }
        }, 30)
    }
    </script>
</body>

</html>

6.缓动函数-让div可以做同时修改多个样式

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    * {
        padding: 0;
        margin: 0;
    }

    div {
        position: absolute;
        top: 40px;
        width: 200px;
        height: 200px;
        background-color: #f99;
        border-radius: 10px;
    }
    </style>
</head>

<body>
    <button>50</button>
    <div></div>
    <script>
    // 需求: 让div同时做多个动画效果

    var btn1 = document.querySelectorAll("button")[0];
    var box = document.querySelector("div");

    btn1.onclick = function() {
        animate(box, { "height": 400, "width": 400, "left": 400, "top": 400});
    }

    // 封装
    // 把写死的值提取出来做参数
    // 参数: 
    //  element 做动画的元素
    //  obj, 是一个对象,对象里面的键值对就是需要做的动画效果
    function animate(element, obj) {
        clearInterval(element.timerid);
        element.timerid = setInterval(function() {

            for (var k in obj) {
                // k ==> 需要做的样式名  width height
                // obj[k] ==> 样式值

                var attr = k;
                var target = obj[k];

                // 1. 首先获取div当前的attr参数对应的样式
                // var current = element.offsetLeft;
                var current = window.getComputedStyle(element, null)[attr];

                // 坑: current是带了单位,不方便下面计算
                // 所以需要去掉px
                current = parseInt(current);


                // 2. 来一个终点值 ,通过参数来传递

                // 3. 每次在当前位置上移动一段距离
                var step = (target - current) / 10;

                // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
                //  保证让step 每次移动的距离是1px,肯定能够移动到终点
                step = step > 0 ? Math.ceil(step) : Math.floor(step);

                current += step;
                element.style[attr] = current + "px";

                if (current == target) {
                    // 由于最后是1px1px移动到终点,所以current 肯定能等于target
                    // 到终点了,清除定时器
                    clearInterval(element.timerid);
                }
            }
        }, 30)


        // 小结: 
        //  第二个参数现在变成了一个对象,对象里面可以写多个键值对(需要做的样式和样式值)
        //  在定时器内部,for循环这个对象
        //  

    }
    </script>
</body>

</html>

7.缓动函数-修复定时器bug

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    * {
        padding: 0;
        margin: 0;
    }

    div {
        position: absolute;
        top: 40px;
        width: 200px;
        height: 200px;
        background-color: #f99;
        border-radius: 10px;
    }
    </style>
</head>

<body>
    <button>50</button>
    <div></div>
    <script>
    // 需求: 让div同时做多个动画效果,而且每个动画效果都能到达终点
    //  每个动画效果都能到达终点,到达了终点才清除定时器,现在的问题是只要有一个样式到达了终点,就把定时器黑清除掉。

    // 难点: 怎么知道所有的样式都到达了终点。
    // 假设成立法:
    //  1. 假设一种情况
    //  2. 尝试推翻假设
    //  3. 经过1,2步骤就可以确认假设是否正确


    var btn1 = document.querySelectorAll("button")[0];
    var box = document.querySelector("div");

    btn1.onclick = function() {
        animate(box, { "height": 510, "width": 600});
    }

    // 封装
    // 把写死的值提取出来做参数
    // 参数: 
    //  element 做动画的元素
    //  obj, 是一个对象,对象里面的键值对就是需要做的动画效果
    function animate(element, obj) {
        clearInterval(element.timerid);

        element.timerid = setInterval(function() {

            // 1. 假设一种情况
            var flag = true; // 假设所有的样式都到达了终点

            //  2. 尝试推翻假设
            for (var k in obj) {
                // k ==> 需要做的样式名  width height
                // obj[k] ==> 样式值

                var attr = k;
                var target = obj[k];

                // 1. 首先获取div当前的attr参数对应的样式
                // var current = element.offsetLeft;
                var current = window.getComputedStyle(element, null)[attr];

                // 坑: current是带了单位,不方便下面计算
                // 所以需要去掉px
                current = parseInt(current);

                // 2. 来一个终点值 ,通过参数来传递

                // 3. 每次在当前位置上移动一段距离
                var step = (target - current) / 10;

                // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
                //  保证让step 每次移动的距离是1px,肯定能够移动到终点
                step = step > 0 ? Math.ceil(step) : Math.floor(step);

                // console.log(step);


                current += step;
                element.style[attr] = current + "px";

                if (current != target) {
                    // 此时的样式动画没有到达对应的终点值
                    // 说明假设失败
                    flag = false;
                }
            }

            // 3. 在for循环,就可以知道了假设是否正确了
            // console.log(flag);

            if(flag){
                // 表示假设成立 -- 清除定时器
                clearInterval(element.timerid);
            }
        }, 30)


        // 小结: 
        //  第二个参数现在变成了一个对象,对象里面可以写多个键值对(需要做的样式和样式值)
        //  在定时器内部,for循环这个对象
        //  

    }
    </script>
</body>

</html>

8.缓动函数-添加回调函数

在这里插入图片描述

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    * {
        padding: 0;
        margin: 0;
    }

    div {
        position: absolute;
        top: 40px;
        width: 200px;
        height: 200px;
        background-color: #f99;
        border-radius: 10px;
    }
    </style>
</head>

<body>
    <button>50</button>
    <div></div>
    <script>
    // 需求: 让div先 left = 600, 到达了600之后,在top= 300,之后在变成圆角

    // 难点:怎么知道left到了600之后,在去开启一个定时器


    var btn1 = document.querySelectorAll("button")[0];
    var box = document.querySelector("div");

    btn1.onclick = function() {
        animate(box, { "left": 600 }, function () {
            animate(box, {"top": 300}, function () {
                animate(box, {"borderRadius": 100})
            });
        });
    }

    // 封装
    // 把写死的值提取出来做参数
    // 参数: 
    //  element 做动画的元素
    //  obj, 是一个对象,对象里面的键值对就是需要做的动画效果
    function animate(element, obj, fn) {

        clearInterval(element.timerid);

        element.timerid = setInterval(function() {

            // 1. 假设一种情况
            var flag = true; // 假设所有的样式都到达了终点

            //  2. 尝试推翻假设
            for (var k in obj) {
                // k ==> 需要做的样式名  width height
                // obj[k] ==> 样式值

                var attr = k;
                var target = obj[k];

                // 1. 首先获取div当前的attr参数对应的样式
                // var current = element.offsetLeft;
                var current = window.getComputedStyle(element, null)[attr];

                // 坑: current是带了单位,不方便下面计算
                // 所以需要去掉px
                current = parseInt(current);

                // 2. 来一个终点值 ,通过参数来传递

                // 3. 每次在当前位置上移动一段距离
                var step = (target - current) / 10;

                // 对step做处理,让其最小值是1,对step做向上取整 Math.ceil()
                //  保证让step 每次移动的距离是1px,肯定能够移动到终点
                step = step > 0 ? Math.ceil(step) : Math.floor(step);

                // console.log(step);


                current += step;
                element.style[attr] = current + "px";

                if (current != target) {
                    // 此时的样式动画没有到达对应的终点值
                    // 说明假设失败
                    flag = false;
                }
            }

            // 3. 在for循环,就可以知道了假设是否正确了
            // console.log(flag);

            if(flag){
                // 表示假设成立 -- 清除定时器
                clearInterval(element.timerid);

                fn && fn();
            }
        }, 30)


        // 小结: 
        //  已经让div可以实现先后顺序动画效果
        //   给animate添加了第三个参数,参数为函数,函数用来当一个动画效果执行结束了,就立即执行该参数。可以在该函数中即可调用animate执行其他的动画效果。

    }
    </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        // 1. 缓动动画初体验
        //      var step = (target - current) / 10;
        // 2. 实现可以左右缓动移动
        //      对step做了处理
        //      step向上取整, 让step最小值都是1px
        //      step向下取整
        //   判断step的正负,step > 0 step向上取整
        // 3. 让div做任意样式的动画
        //      window.getComputedStyle()
        //      animate(box, "width", 400);
        // 4. 让div同时做多个动画效果
        //      传参,参数为对象
        //      animate(box, {"left": 800, "top": 300})
        //      animate 内部处理方式, for循环遍历传递的参数
        //      解决没有都运动到终点bug
        //      假设成立法,让所有的样式都运动到了终点才清除的定时器
        // 5. 让div在执行动画结束之后,可以再次做其他动画效果
        //      添加了一个回调函数
        //      一定要注意: 清除定时器的时候才执行那个回调函数。
        //      fn && fn();  只有在fn传递了函数的情况下,才执行fn()
    </script>
</body>
</html>

9.手风琴特效

手风琴是很常见的特效,希望大家都能掌握

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    * {
        margin: 0;
        padding: 0;
        list-style: none;
    }

    #accordion {
        width: 1200px;
        height: 400px;
        margin: 100px auto;
        border: 2px solid pink;
        position: relative;
        overflow: hidden;
    }

    #accordion li {
        width: 1200px;
        height: 400px;
        position: absolute;
        top: 0;
        left: 0;
    }
    </style>
</head>

<body>
    <div id="accordion">
        <ul>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>

    <script src="../animate_final.js"></script>

    <script>
        // 功能1: 给每一个li设置背景图片
        //  思路: 
        //  1. 找对象 找所有的li元素
        //  2. for循环,给每一个li都要设置背景图片
        //  

        // 功能2: 给li设置left,排布位置
        //  思路: 
        //      1. li的left 排布的规律: 下标 * 240


        // 功能3: 
        //  思路: 
        //   1. 每一个li都注册 onmouseover
        //   2. 鼠标移入上去干嘛?
        //   3. 修改每一个li的left位置, for循环进行修改
        //   4.  把li分成两拨
        //      下标 <= 当前li的下标, left 排布方式: 下标 * 100
        //      下标 > 当前li的下标,  left 排布方式: 下标 * 100 + 700


        // 功能4: 鼠标离开事件 --- 给box注册onmouseout
        //  就是把每一个li的left 恢复成原来默认的布局方式


        // 1.
        var box = document.querySelector("#accordion");
        var lis = document.querySelectorAll("#accordion li");

        // 2.
        for (var i = 0; i < lis.length; i++) {
            // 存下标
            lis[i].index = i;

            //  功能1:
            lis[i].style.backgroundImage = "url(images/"+ (i + 1) +".jpg)";


            // 功能2:这是一开始没有动画效果的
            lis[i].style.left = i * 240 + "px";

            // 功能3: 
            lis[i].onmouseover = function () {
                for (var i = 0; i < lis.length; i++) {
                    if(i <= this.index){
                        // <=  ,等于是相当于把当前的li去做left 动画, i * 100
                        animate(lis[i], {"left": i * 100})
                    }else{
                        animate(lis[i], {"left": i * 100 + 700})
                    }
                }
            }
        }


        box.onmouseout = function () {
            for (var i = 0; i < lis.length; i++) {
                animate(lis[i], {"left": i * 240})
            }
        }

        // 小结: 
        //  设置背景图片 + left 位置
        //  li的left  分成两拨(每个li的下标和当前li的下标做比较)
    </script>
</body>

</html>

十二、三大家族

1.offset家族

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

2.scroll家族

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #f99;
            padding: 10px;
            border: 10px solid #000;
            /*overflow: hidden;*/
            overflow: scroll;
        }
    </style>
</head>
<body>

    <div>
        asfweregrthyewqdewfrgrthyjrewdqfewrgrtyjukyjthrgefwdqfwrgethrytjytrefwrgrth
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
        按时收费威锋网费
    </div>

    <script>
        // scroll家族:
        //  scrollWidth  scrollHeight  scrollTop scrollLeft

        var div = document.querySelector("div");

        // scrollWidth  scrollHeight 是内容的宽高

        /*console.log(div.offsetWidth); // 真实的宽度
        console.log(div.scrollWidth);

        // offsetHeight 只和div的宽高相关,和内容无关
        console.log(div.offsetHeight);
        console.log(div.scrollHeight);*/


        // scrollTop scrollLeft : 卷曲的距离
        // scrollLeft  水平方向的卷曲距离
        // console.log(div.scrollTop);  // 获取div的卷曲垂直方向距离
            // 如果卷曲的值是0,没有卷曲,或者是没有滚动条

        // 需求: 让div的滚动条在滚动的时候,就要实时的获取卷曲的距离
        // onscroll: 当滚动条在滚动的时候触发

        // 这是给div注册scroll滚动事件
        div.onscroll = function () {
            // console.log(div.scrollTop);
            console.log(div.scrollLeft);
        }

        // 小结:
        //  scroll 家族
            // scrollWidth  scrollHeight  获取的是内容的宽高
            // scrollLeft  scrollTop  内容的卷曲距离 (水平和垂直方向的)
            // onscroll 滚动条滚动的时候触发的事件,滚动条滚动了一像素就会触发
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        body{
            height: 4000px;
            width: 4000px;
        }
    </style>
</head>
<body>
    <script>
        // 使用场景

        // 获取页面的卷曲的距离
        //  获取存在兼容问题:
        //      老版本的浏览器: 通过html的scrollTop来获取,或者是通过body的scrollTop去获取
        //      新版浏览器:     通过 window.pageYOffset
        // 需要给window注册onscroll事件

        window.onscroll = function () {
            // var scrollTop = document.documentElement.scrollTop || document.body.scrollTop || 0;

            // var scrollTop = window.pageYOffset;

            // 新老结合兼容  -- 垂直方向的卷曲距离
            var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;


            // 获取水平方向的卷曲距离
            var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;

            console.log(scrollLeft);
        }



        // 小结:
        //  页面级别的滚动
        //  给window注册onscroll
        //  获取页面的卷曲距离,有兼容性
        //      新: window.pageYOffset
        //      老: html/body的scrollTop
    </script>
</body>
</html>

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
    * {
        margin: 0;
        padding: 0
    }

    img {
        vertical-align: top;
        width: 100%;
    }

    .main {
        margin: 0 auto;
        width: 1000px;
        margin-top: 10px;

    }

    .fixed {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
    }
    </style>
</head>

<body>
    <div class="top" id="topPart">
        <img src="images/top.png" alt="" />
    </div>
    <div class="nav" id="navBar">
        <img src="images/nav.png" alt="" />
    </div>
    <div class="main" id="mainPart">
        <img src="images/main.png" alt="" />
    </div>
    <script>
        // 思考:
        //  1. 找对象
        //  2. 给window 注册onscroll
        //  3. 获取页面垂直方向的卷曲距离  scrollTop
        //  4.  scrollTop 和 topPart的高度做比较
        //        4.1 scrollTop >= topPart的高度,需要让navBar进行固定定位
        //          会脱标, 不占位置,底下的mainPart会跑上面去
        //          解决办法: 给mainPart设置marginTop = 10 + navBar的高度
                    // 4.2  scrollTop < topPart的高度, 让navBar取消固定定位
                    // 当navBar取消固定定位,mainPart设置marginTop = 10

        //  1
        var navBar = document.querySelector("#navBar");
        var topPart = document.querySelector("#topPart");
        var mainPart = document.querySelector("#mainPart");

        // 2
        window.onscroll = function () {
            // 3.
            var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

            // 4.
            if (scrollTop >= topPart.offsetHeight) {
                navBar.className = "nav fixed";
                mainPart.style.marginTop = 10 + navBar.offsetHeight + "px";
            }else{
                navBar.className = "nav";
                mainPart.style.marginTop = "10px";
            }
        }

        // 小结:
        //  scrollTop 
        //  window.onscroll 
    </script>
</body>

</html>

3.client家族

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 100px;
            height: 100px;
            padding: 10px;
            border: 10px solid #000;
    
            border-left-width: 40px;
            border-top-width: 60px;

            background-color: #f99;
        }
    </style>
</head>
<body>
    
    <div>
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    爱上纷纷是废物废物范围
    </div>

    <script>
        // client家族
        // clientWidth  clientHeigth clientLeft clientTop
        var div = document.querySelector("div");
        
        // console.log(div.offsetHeight);

        // // 如果内容没有撑开,scrollHeight 和 clientHeight一样大小。
        // console.log(div.scrollHeight);
        // console.log(div.clientHeight);
        // console.log(div.clientWidth);

        // clinetTop  clientLeft
        console.log(div.clientTop);  // 上边框的大小
        console.log(div.clientLeft);// 左边框的大小

        // 小结:
        //  clientWidth  clientHeight  可视区的宽高
getNode
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        // 获取页面的可视区大小

        // 获取也有兼容性问题
        // 老版本浏览器:  通过html或者是body的clientWidth
        // 新版本的浏览器: window.innerWidth   window.innerHeight


        // 兼容写法
        var clientW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
        var clientH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;


        console.log(clientW, clientH);


        // 实时的获取可视区的大小
        // onresize  当页面可视区在发生改变的时候触发

        window.onresize = function () {
            var clientW = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
            var clientH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

            console.log(clientW, clientH);
        }



        // 小结:
        //  clientWidth  clientHeight 页面的可视区的大小
        //  onresize 当页面大小发生改变触发
        //   新: window.innerWidth
        //   老: html、body去获取clientWidth


        // 三大家族:
        // offset: offsetWidth  offsetHeight  offsetLeft  offsetTop
        // scroll: scrollWidth  scrollHeight  scrollLeft  scrollTop
        // client: clientWidth  clientHeight  clientLeft  clientTop


        // offset 家族的成员都常用: 用于获取元素的大小和位置信息
        // scroll家族:获取元素的内容的宽高,不常用,常用的scrollTop (获取页面的垂直方向的卷曲距离)
        //      onscroll 事件
        // client家族: 常用的就是可视区的宽高
        //      onresize 事件
    </script>
</body>
</html>

十三、事件对象

1.事件对象的概述

在这里插入图片描述

2.获取事件对象

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        // 事件对象: 在事件触发时候,,会产生一个事件对象(这个对象里面存储了一些和事件相关的信息)
        //  比如说:点击事件,鼠标事件对象,里面就有和鼠标相关的信息
        //          键盘事件,键盘事件对象, 存储了跟键盘相关的信息


        // 获取事件对象

        // 存在兼容性问题

        // 新的浏览器: 只需要在事件处理函数里面指定一个形参即可,这个形参就是事件对象
        // IE678 : window.event 来获取的


        // 形参可以任何指定
        document.onclick = function (e) {
            // console.log(e);

            // 处理事件对象的兼容性问题“
            e = e || window.event;

            console.log(e);
        }


        // 小结:
        //  事件对象: 存储了和事件相关的信息
        //  获取事件对象:
        //    1. ie:  window.event
        //    2. 给事件处理函数指定一个形参,通过形参来获取事件对象
             //  兼容写法: e = e || window.event;
    </script>
</body>
</html>

3.事件对象的常用属性

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    
    <style>
        body{
            height: 4000px;
        }
    </style>

</head>
<body>
    <script>
        // 事件对象常见的属性

        // 鼠标的事件对象
        // document.onclick = function (e) {
        //     // console.log(e);

        //     // 在鼠标的事件对象中,常用的属性有三个
        //     // clientX clientY : 鼠标距离可视区左边和上边的距离
        //     // pageX pageY:    鼠标距离页面左边和上边的距离
        //     // screenX  screenY:  鼠标距离屏幕左边和上边的距离
        //     // 上面三个属性都是用来获取鼠标的距离


        //     console.log("clientX  " + e.clientX);
        //     console.log("pageX  " + e.pageX);
        //     console.log("screenX  " + e.screenX);

        //     // 当页面没有滚动条的时候,clientY 和 pageY 是相等的
        //     console.log("clientY  " + e.clientY);
        //     console.log("pageY  " + e.pageY);
        //     console.log("screenY  " + e.screenY);
        // }


        // 键盘的事件对象
        document.onkeyup = function (e) {
            console.log(e);
            // 键盘的事件对象中,常用的属性就一个,keyCode 键盘码
            // 通过这个键盘码就可以确认按键是按了哪个键。
        }



        // 小结:
        // 常用属性: 
        //  鼠标事件对象: 
        //         client  鼠标距离可视区的鼠标位置信息
        //         page   相当于页面
        //         screen : 相对于屏幕
        //  键盘事件对象:
        //          keyCode: 键盘码

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

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        body{
            height: 4000px;
        }
    </style>
</head>

<body>
    <img src="images/tianshi.gif" alt="">

    <script>
        // 功能: 鼠标在页面中移动的时候,让图片跟随鼠标移动

        // 关键: 获取鼠标的位置信息,从而给 图片设置left 、top

        // onmousemove: 鼠标在页面中移动的时候触发的事件

        var ts = document.querySelector("img");

        document.onmousemove = function (e) {
            // 如果采用的是绝对定位, 最好采用pageX, 以为在没有滚动条的时候,clientY和pageY是相等的。
            // 一旦有了滚动条,采用pageY更合适。
            /*ts.style.position = "absolute";
            ts.style.left = e.pageX + "px";  // 设置元素的left、top样式,必须要有定位
            ts.style.top = e.pageY + "px";*/

            
            // 其他写法
            ts.style.position = "fixed";  // 固定定位,相对于的是浏览器
            ts.style.left = e.clientX + "px";
            ts.style.top = e.clientY + "px";
        }
    </script>
</body>

</html>

4.拖拽特效

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #f99;
            position: absolute;
            cursor: move;
        }
    </style>
</head>
<body>
    
    <div></div>

    <script>
        // 拖拽案例: 涉及到三个事件
        //  鼠标摁下事件 : onmousedown
        //  鼠标移动事件 : onmousemove
        //  鼠标抬起事件 : onmouseup


        // 案例实现的效果:
        //     1. 需要在div上摁下去
        //     2. 在页面中移动的时候,需要让div跟随鼠标移动
        //     3. 在页面中抬起鼠标的时候,让div不需要再跟随鼠标移动


        var div = document.querySelector("div");


        // 节流阀: 让事件有限制的触发

        var open = true; // 阀门现在是关闭状态,该阀门用来控制鼠标移动的触发


        // 在div上摁下去,给div注册鼠标按下去
        div.onmousedown = function () {
            // 在div上摁下去了,就把阀门打开
            console.log("鼠标摁下去了");

            open = true;

        }

        // 在页面中移动的时候,document
        document.onmousemove = function(){
            // 现在的bug: 鼠标只要移动到页面中,就会打印
            // 效果: 必须先在div上摁下去,才出发鼠标移动事件
            // console.log("鼠标移动了");

            if(open){
                // 只有阀门是打开的状态才能触发
                console.log("鼠标移动了");
            }

        }

        // 在页面中抬起鼠标的时候
        document.onmouseup = function () {
            console.log("鼠标抬起来了");

            // 鼠标抬起来了,把阀门在次关闭
            open = false;
        }

        // 小结;
        //  抬起:onmouseup
        //  摁下: onmousedown
        //  移动: onmousemove
        
        //  节流阀: 首先阀门关闭或者打开
        //           某一个条件把阀门打开
        //           另外一个条件把阀门关闭。
        //           通过关闭和打开阀门实现让事件有限制的去执行。

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #f99;
            position: absolute;
            cursor: move;
        }
    </style>
</head>
<body>
    
    <div></div>

    <script>
        // 拖拽案例: 涉及到三个事件
        //  鼠标摁下事件 : onmousedown
        //  鼠标移动事件 : onmousemove
        //  鼠标抬起事件 : onmouseup


        // 案例实现的效果:
        //     1. 需要在div上摁下去
        //     2. 在页面中移动的时候,需要让div跟随鼠标移动
        //     3. 在页面中抬起鼠标的时候,让div不需要再跟随鼠标移动


        var div = document.querySelector("div");


        // 节流阀: 让事件有限制的触发
        var open = false; // 阀门现在是关闭状态,该阀门用来控制鼠标移动的触发

        // 在div上摁下去,给div注册鼠标按下去
        div.onmousedown = function () {
            // 在div上摁下去了,就把阀门打开
            console.log("鼠标摁下去了");
            open = true;
        }

        // 在页面中移动的时候,document
        document.onmousemove = function(e){
            // 现在的bug: 鼠标只要移动到页面中,就会打印
            // 效果: 必须先在div上摁下去,才出发鼠标移动事件
            // console.log("鼠标移动了");

            if(open){
                // 只有阀门是打开的状态才能触发
                console.log("鼠标移动了");

                div.style.left = e.pageX + "px";
                div.style.top = e.pageY + "px";
            }

        }

        // 在页面中抬起鼠标的时候
        document.onmouseup = function () {
            console.log("鼠标抬起来了");
            // 鼠标抬起来了,把阀门在次关闭
            open = false;
        }

        // 小结;
        //  抬起:onmouseup
        //  摁下: onmousedown
        //  移动: onmousemove
        
        //  节流阀: 首先阀门关闭或者打开
        //           某一个条件把阀门打开
        //           另外一个条件把阀门关闭。
        //           通过关闭和打开阀门实现让事件有限制的去执行。

        // 细节问题: 
        //   不要把mousemove mouseup事件注册在div上,容易弄丢div。给document整个页面注册。 
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #f99;
            position: absolute;

            left: 200px;
            top: 300px;

            cursor: move;
        }
    </style>
</head>
<body>
    
    <div></div>

    <script>
        // 拖拽案例: 涉及到三个事件
        //  鼠标摁下事件 : onmousedown
        //  鼠标移动事件 : onmousemove
        //  鼠标抬起事件 : onmouseup


        // 案例实现的效果:
        //     1. 需要在div上摁下去
        //     2. 在页面中移动的时候,需要让div跟随鼠标移动
        //     3. 在页面中抬起鼠标的时候,让div不需要再跟随鼠标移动


        // 思路: 
        //   获取鼠标距离页面左边的距离   pageX
        //   减去 div距离offsetParent之间的距离 (就是到body之间的距离)
        //   相减的结果: 鼠标在div内的距离  
        //           这个结果,在鼠标在div上摁下去的时候就可以获取到了
        //   在鼠标移动的时候,鼠标的位置减去 上面得到的结果

        var div = document.querySelector("div");

        // 节流阀: 让事件有限制的触发
        var open = false; // 阀门现在是关闭状态,该阀门用来控制鼠标移动的触发

        // 两个变量用来存储鼠标在div上摁下去,鼠标到div之间的距离
        var disX = 0;
        var disY = 0; 

        // 在div上摁下去,给div注册鼠标按下去
        div.onmousedown = function (e) {
            // 在div上摁下去了,就把阀门打开
            open = true;

            // 鼠标在div上摁下去,鼠标到div的距离
            disX = e.pageX - div.offsetLeft;
            disY = e.pageY - div.offsetTop;
            // console.log(disX, disY);
        }

        // 在页面中移动的时候,document
        document.onmousemove = function(e){
            // 现在的bug: 鼠标只要移动到页面中,就会打印
            // 效果: 必须先在div上摁下去,才出发鼠标移动事件
            // console.log("鼠标移动了");

            if(open){
                // 只有阀门是打开的状态才能触发
                div.style.left = e.pageX - disX + "px";
                div.style.top = e.pageY - disY + "px";
            }
        }

        // 在页面中抬起鼠标的时候
        document.onmouseup = function () {
            // 鼠标抬起来了,把阀门在次关闭
            open = false;
        }

        
        // 小结;
        //  抬起:onmouseup
        //  摁下: onmousedown
        //  移动: onmousemove
        
        //  节流阀: 首先阀门关闭或者打开
        //           某一个条件把阀门打开
        //           另外一个条件把阀门关闭。
        //           通过关闭和打开阀门实现让事件有限制的去执行。

        // 细节问题: 
        //   不要把mousemove mouseup事件注册在div上,容易弄丢div。给document整个页面注册。 
    </script>
</body>
</html>

十四、注册事件的方式

1.on+事件名称

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        /*document.onclick = function () {
            console.log(1);
        }
        // 使用on注册事件,存在覆盖问题(同一个元素、同一个事件)
        document.onclick = function () {
            console.log(2);
        }

        // 解绑元素的事件
        document.onclick = null;*/


        // 新的注册事件的方式
        // addEventListener(event, fn, useCapture);  // 添加事件监听, 注册事件, 绑定事件
        // 参数: 
        //  event: 事件名: onclick click  onmousemove mousemove,这里的事件名是不带on的
        //  fn: 事件处理函数
        //  useCapture: 是否使用事件捕获,默认值是false,可以省略


        // 坑: 如果希望注册的事件能够解绑,不能下面这种方式来注册, 这样注册的事件是无法解绑的
        document.addEventListener("click", function () {
            console.log(3);
        })


        // 要想解绑成功,需要把事件处理函数单独拿出来,弄一个函数名即可
        function fn() {
            console.log(4);
        }
        // 使用addEventListener 可以解决使用on存在的覆盖问题
        document.addEventListener("click", fn);



        // 解绑
        document.removeEventListener("click", fn);


        // 使用addEventListener注册的事件如何解绑
        // removeEventListener(event, fn, useCapture);
        // 参数同 addEventListener的参数

        // 注意点: 使用removeEventListener 解绑 addEventListener注册的事件 不能像下面这么写
        // 要想解绑成功,第二个参数必须是一个函数名,不能是匿名函数
        /*document.removeEventListener("click", function () {
            console.log(3);
        })*/



        // 小结:
        //  注册事件的方式:
        //      1. on + 事件名   存在覆盖问题
        //              解绑: onclick = null;
        //      2. addEventListener(event, fn);  存在兼容性问题,ie678不支持
        //              解绑: removeEventListener
        //          注意: 要想解绑: 不能写匿名函数,一定要是写函数名
    </script>
</body>
</html>

2.注册事件的新方式

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

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

        // 坑: 如果希望注册的事件能够解绑,不能下面这种方式来注册, 这样注册的事件是无法解绑的
        document.addEventListener("click", function foo() {
            console.log(3);
            console.log(foo);
        })  


        // 把函数声明作为参数传递的时候,解析成了具名函数表达式的写法

        // 具名函数表达式中function关键字后面的函数名,在外面获取不到,只能在函数内部去使用这个函数名
        var fn = function bar() {
            console.log(1);
            console.log(bar);
        }
        fn()


        // console.log(foo);

        // 解绑
        // document.removeEventListener("click", foo);

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        // attachEvent与detachEvent
        // 参数事件名,必须要带上on

        // ie提出来注册事件的方式

        var fn = function(){
            console.log(1);
        };

        document.attachEvent("onclick", fn)

        document.detachEvent("onclick", fn);
    </script>
</body>
</html>

十五、事件流

1.事件冒泡

在这里插入图片描述

2.事件捕获(了解)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .father{
            width: 400px;
            height: 400px;
            background-color: #f99;
        }
        .son{
            width: 200px;
            height: 200px;
            background-color: yellow;
        }
        .sun{
            width: 100px;
            height: 100px;
            background-color: green;
        }
    </style>
</head>
<body>

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

    <script>

        var father = document.querySelector(".father");
        var son = document.querySelector(".son");
        var sun = document.querySelector(".sun");

        var arr = [];

        for (var i = 0; i < arr.length; i++) {
            // 给数组中的每一项注册点击了事件
            // 使用on注册的事件只能在事件冒泡阶段触发
            /*arr[i].onclick = function () {
                console.log(this);
            }*/

            // addEventListener(event, listener, useCapture)
            arr[i].addEventListener("click", function () {
                console.log(this);

                // useCapture 值为false,表示在事件冒泡阶段触发
            }, false)
        }


        // 事件冒泡 事件捕获 是事件的底层机制,只要触发了事件,这个事件就会传播(不是说所有的元素都有了对应的事件才会传播,跟注册事件没有关系)。
    </script>
</body>
</html>

3.事件的三个阶段

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .father{
            width: 400px;
            height: 400px;
            background-color: #f99;
        }
        .son{
            width: 200px;
            height: 200px;
            background-color: yellow;
        }
        .sun{
            width: 100px;
            height: 100px;
            background-color: green;
        }
    </style>
</head>
<body>

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

    <script>
        var father = document.querySelector(".father");
        var son = document.querySelector(".son");
        var sun = document.querySelector(".sun");

        document.addEventListener("click", function(e){
            console.log(this);
            // 该事件在捕获阶段触发
        }, true);

        document.body.addEventListener("click", function(e){
            console.log(this);
            // 该事件在冒泡阶段触发
            e.stopPropagation();
        }, false);

        father.addEventListener("click", function(e){
            console.log(this);
        }, true);

        son.addEventListener("click", function(){
            console.log(this);
        }, false);

        sun.addEventListener("click", function(){
            console.log(this);
        }, true);


        // 捕获阶段和冒泡阶段的事件只会在对应的阶段触发对应的事件
        // 注册的事件是在捕获阶段触发的话,那么只会在捕获阶段执行,不会再冒泡阶段在执行一次。

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

4.常见的事件

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值