JavaScript基础--DOM部分02--李南江

目录

1.关闭广告

2.图片展示

3.鼠标的移入移出事件

4.商品展示

5.表单校验

6.焦点事件

7.闭包

8.索引同步

9.排他思想

10.Tab选项卡-面向对象

11.全选-反选

12.Date 时间对象

13.Date 时间对象-计算时间差值

14.秒杀效果

15.时钟效果

16.长图效果

17.匀速动画

18.缓动动画

19.轮播图

20.无限轮播图

21.自动轮播图

22.匀速动画-加强版

23.缓速动画-加强版

24.联动动画-关闭弹窗

25.添加事件的三种方式

26.事件对象

27.事件执行的三个阶段

28.事件位置

29.正则表达式

30.日期格式化-高级版


1.关闭广告

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>关闭广告</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        div{
            /* 设置div的高度与宽度必须比背景图片的尺寸大,这样才能容纳 */
            /* width: 300px;
            height: 380px; */
            /* 默认div的宽高就是img图片的宽高 */
            /* border: 1px solid red; */
            /* 添加背景图片 */
            /* background: url("images/sina-ad.png") no-repeat; */

            /* position: absolute;
            bottom: 0;
            left: 0; */
            /* 固定定位:不随着滚动条的滚动而滚动 */
            position: fixed;
            bottom: 0;
            left: 0;
        }
        div>img:first-child{
            /* 绝对定位:就是相对于body浏览器或者某个定位流中的祖先元素来定位 */
            position: absolute;
            /* top: 0; */
            top: -17px;
            right: 0;
        }
    </style>

</head>
<body>
    <div>
        <img src="images/close.jpg" alt="">
        <img src="images/sina-ad.png" alt="">
    </div>
    
    <script>
        // 1.获取元素
        let oImg = document.querySelector("div>img:first-child");
        // 2.绑定点击事件
        oImg.onclick = function(){

            // 获取元素
            let oDiv = document.querySelector("div");
            // 删除元素
            document.body.removeChild(oDiv);

            // // 2.1 找到按钮的父元素
            // let oDiv = this.parentNode;
            // // console.log(oDiv);
            // // 2.2 删除广告元素
            // oDiv.parentNode.removeChild(oDiv);
            
        };
    </script>
</body>
</html>

2.图片展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图片展示</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        div{
            width: 670px;
            /* height: 1000px; */
            /* border: 1px solid red; */
            margin: 100px auto;
        }
        ul{
            list-style: none;            
            /* border: 1px solid red; */
            /* 弹性布局 */
            display: flex;
            /* 两端对齐,元素之间的间隔都相等 */
            justify-content: space-between;
        }
        /* ul li{
            float: left;
            margin-right: 14px;
        } */
        ul>li>img{
            width: 120px;
            /* 底端对齐 */
            vertical-align: bottom;
        }
    </style>
</head>
<body>
    <div>
        <img src="images/ad1.jpg" alt="">
        <ul>
            <li><img src="images/ad1.jpg" alt=""></li>
            <li><img src="images/ad2.jpg" alt=""></li>
            <li><img src="images/ad3.jpg" alt=""></li>
            <li><img src="images/ad4.jpg" alt=""></li>
            <li><img src="images/ad5.jpg" alt=""></li>
        </ul>
    </div>
    
    <script>
        let oImg = document.querySelector("div>img");
        // 获取列表中存储的所有图片
        let oItems = document.querySelectorAll("ul>li>img");
        // console.log(oItems);           // 数组

        // 遍历数组中的每张图片
        for(let item of oItems){
            
            // 存在性能问题
            // // 绑定点击事件
            // item.onclick = function(){
            //     // 更改大图片img的src地址
            //     // oImg.src = item.src;
            //     // console.log(this);    // 点击的那张图片img(item)
            //     oImg.src = this.src;
            // }

            // 绑定点击事件
            item.onclick = change;

        }

        // 改进
        function change() {
            oImg.src = this.src;
        };
        
        // 不同的对象调用相同的方法,存储在不同的空间,这样很消耗性能
        // let obj1 = { name: "zs" };
        // let obj2 = { name: "ls" };

        // obj1.say = function () {
        //     console.log("hello");
        // }
        // obj2.say = function () {
        //     console.log("hello");
        // }
        // console.log(obj1.say === obj2.say);     // false

        // // 改进
        // let obj1 = {name:"zs"};
        // let obj2 = {name:"ls"};

        // function say() {
        //     console.log("hello");
        // }
    
        // obj1.say = say;
        // obj2.say = say;
        // console.log(obj1.say === obj2.say);     // true 
    </script>
</body>
</html>

3.鼠标的移入移出事件

    <style>
        *{
            margin: 0;
            padding: 0;
        }
        div{
            width: 200px;
            height: 200px;
            background-color: pink;
        }
    </style>

    <div></div>
        // 获取元素
        let oDiv = document.querySelector("div");

(1).鼠标移入事件

  • onmouseover
  • onmouseenter     (推荐使用)
        // 1.鼠标移入事件
        // oDiv.onmouseover = function () {
        //     console.log("鼠标移入事件");
        // };
        // 注意点: 对于初学者来说, 为了避免未知的一些BUG, 移入事件 建议使用 onmouseenter
        oDiv.onmouseenter = function () {
            console.log("鼠标移入事件");
        };

(2).鼠标移出事件

  • onmouseout
  • onmouseleave     (推荐使用)
        // 2.鼠标移出事件
        // oDiv.onmouseout = function () {
        //     console.log("鼠标移出事件");
        // };
        // 注意点: 对于初学者来说, 为了避免未知的一些BUG, 移出事件 建议使用 onmouseleave
        oDiv.onmouseleave = function () {
            console.log("鼠标移出事件");
        };

(3).鼠标移动事件

  • onmousemove 
        // 3.鼠标移动事件
        oDiv.onmousemove = function () {
            console.log("鼠标移动事件");
        }

4.商品展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品展示</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }        
        div{
            width: 430px;
            /* 让div自身居中对齐;第一个参数为margin-top上外边距*/
            margin: 100px auto;
            border: 1px solid black;
        }
        ul{
            list-style: none;
            /* 弹性布局 */
            display: flex;
            justify-content: space-between;
        }
        ul>li>img{
            width: 80px;
            /* 底部对齐 */
            vertical-align: bottom;
        }

        /* 解决鼠标移入时,添加边框后,其他图片被拥挤的问题 */
        ul>li{
            /* 添加边框,transparent:透明颜色 */
            border: 2px solid transparent; 
            /*  */
            box-sizing: border-box;
            
        }
            
        .border{
            /* 设置边框 */
            border: 2px solid skyblue;
        }

    </style>
</head>
<body>

    <div>
        <img src="images/pic1.jpg" alt="">
        <ul>
            <li><img src="images/pic1.jpg" alt=""></li>
            <li><img src="images/pic2.jpg" alt=""></li>
            <li><img src="images/pic3.jpg" alt=""></li>
            <li><img src="images/pic4.jpg" alt=""></li>
            <li><img src="images/pic5.jpg" alt=""></li>
        </ul>
    </div>
  
    <script>
        // 1.获取元素
        let images = document.querySelectorAll("ul>li>img");
        let bigImage = document.querySelector("div>img")
        // console.log(images);   //数组,保存了所有的小图片
        // 2.遍历图片数组
        for(let image of images){
            // 3.监听鼠标移入事件
            image.onmouseenter = function(){
                // 3.1 修改大图片的src地址
                // bigImage.src = image.src;
                // console.log(this)   // 每一张小图片image
                bigImage.src = this.src;
                // 3.2 通过添加类名的方式,添加边框
                // 注意点:是给小图片image的父元素li列表添加边框,而不是给小图片本身添加边框!
                // image.className = "border";
                // console.log(this.parentElement);
                this.parentElement.className = "border";
            }
            // 4.监听鼠标移出事件
            image.onmouseleave = function(){
                // 将类名置空,取消边框
                this.parentElement.className = "";
            }
        }  
    </script>
</body>
</html>

5.表单校验

  • 需求描述
  • 1.账号和密码必须大于等于6位
  • 2.如果账号密码的长度不够就改变input输入框的背景颜色
  • 3.如果用户输入的账号或者密码不符合需求, 那么就不能提交
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>表单校验</title>
</head>
<body>
    <!-- action: 点击提交按钮后,跳转到的地址 -->
    <form action="http://www.it666.com">
        <input type="text" placeholder="请输入账号" class="text">
        <input type="password" placeholder="请输入密码" class="passwd">
        <input type="submit" value="注册" class="submit">
    </form>

    <script>
        /*
        需求:
            1.账号和密码必须大于等于6位
            2.如果账号密码的长度不够就改变input输入框的背景颜色
            3.如果用户输入的账号或者密码不符合需求, 那么就不能提交
        */
        // 1.获取元素
        let Osubmit = document.querySelector(".submit");
        let Otext = document.querySelector(".text");
        let Opasswd = document.querySelector(".passwd");
        // 2.绑定点击事件
        Osubmit.onclick = function(){
            // 注意点: 如果想获取input中输入的内容, 必须通过value属性来获取
            // console.log(Otext.value);
            // 2.1 判断账号是否符合需求
            if(Otext.value.length < 6){
                // 修改背景颜色 
                // 注意:background-color(CSS) ---> backgroundColor (JS)
                Otext.style.backgroundColor= "red";
                return false;
            }else{
                Otext.style.backgroundColor = "#fff";
            }
            // 2.2 判断密码是否符合需求
            if (Opasswd.value.length < 6) {
                Opasswd.style.backgroundColor = "red";
                return false;
            } else {
                Opasswd.style.backgroundColor = "#fff";
            }
        }
    </script>
</body>
</html>

6.焦点事件

    <input type="text">

(1).监听input获取焦点事件

  • onfocus
        oInput.onfocus = function(){
            console.log("获取到了焦点");
        }

(2).监听input失去焦点事件

  • onblur
        oInput.onblur = function() {
            console.log("失去了焦点");
        }

(3).监听input内容改变事件

  • onchange
        // 注意点: onchange事件只有表单失去焦点的时候, 才能拿到修改之后的数据
        oInput.onchange = function(){
            console.log(this.value);
        }

(4).监听input实时内容改变事件

  • oninput
        // 可以时时获取到用户修改之后的数据, 只要用户修改了数据就会调用(执行)
        // 注意点: oninput事件只有在IE9以及IE9以上的浏览器才能使用
        // 在IE9以下, 如果想时时的获取到用户修改之后的数据, 可以通过onpropertychange事件来实现
        oInput.oninput = function(){
            console.log(this.value);
        }

7.闭包

(1).什么是闭包(closure)

  • 闭包是一种特殊的函数

(2).如何生成一个闭包

  • 当一个内部函数引用了外部函数的数据(变量/函数)时, 那么内部的函数就是闭包;
  • 所以只要满足两个条件:"是函数嵌套"、"内部函数引用外部函数数据";

(3).闭包的特点

  • 只要闭包还在使用外部函数的数据, 那么外部的数据就一直不会被释放; 也就是说可以延长外部函数数据的生命周期

(4).闭包的注意点

  • 当后续不需要使用闭包时候, 一定要手动将闭包设置为null, 否则会出现内存泄漏
    function test() {
        var i = 666;   // 局部变量
    }  // 只要代码执行到了大括号结束, i这个变量就会自动释放
    console.log(i);    // Uncaught ReferenceError: i is not defined
    function test() {
        var i = 888;
        // 由于demo函数满足闭包的两个条件, 所以demo函数就是闭包
        return function demo() {
            console.log(i);
        };
    }
    let fn = test();
    fn();   // 888

8.索引同步

  • 默认情况下是:顺序结构, 代码会从上至下的执行, 前面的没执行完后面的不能执行
  • 默认情况下:通过 var 定义的变量, 只要不是定义在函数中,都是全局变量
    // 无法同步
    for(var i=0; i<3; i++){
        // console.log(i);
        function test() {
            console.log(i);   // 3
        }

    }
    // console.log(i);   // 3
    test();
    // 可以同步
    for(var i=0; i<3; i++){   // 0 1 2 3
        // console.log(i);
        function test() {
            console.log(i);  // 0 1 2
        }
        test();
    }
    for(var i = 0; i < 3; i++){     // 0 1 2 3
        // 立即执行函数(等价于以下代码)
        (function test(index) {
            console.log(index);     // 0 1 2
        })(i);

        // function test(index) {   // var index = i;
        //     console.log(index);  // 0 1 2
        // }
        // test(i);
    }

闭包 + 索引同步 练习1:

<body>
    <button>我是按钮1</button>
    <button>我是按钮2</button>
    <button>我是按钮3</button>
<script>
    let oButtons = document.querySelectorAll("button");
    // for(var i=0; i<oButtons.length; i++){
    //     oButton = oButtons[i];
    //     oButton.onclick = function () {
    //         console.log(i);   //此时无论点击哪个按钮,输出都是3
    //     }
    // }

    for(var i=0; i<oButtons.length; i++){
        oButton = oButtons[i];
        (function test(index){   // var index = i;
            // console.log(index); // 0 1 2
            // 注意点: onclick对应的方法由于满足了闭包的条件, 所以onclick对应的方法也是一个闭包
            oButton.onclick = function () {
                console.log(index);
            }
        })(i)
    }
</script>
</body>
  • 在ES6中,如果在循环中通过 let 定义的变量,那么这个变量是一个局部变量
  • for循环中,通过 let 定义的变量,每次执行循环体都会重新定义一个新的,也就是每个循环体都有一个属于自己的变量
  • 只要在块级作用域中定义了一个函数,并且这个函数中用到了块级作用域中的数据,那么这个函数就是闭包
        // 这里的i是全局变量
        for(var i=0; i<3; i++){
            // console.log(i);        // 0 1 2
            function test() {
                console.log(i);      // 3
            }
        }
        test();
        // console.log(i);           // 3

        // 这里的i是局部变量
        for(let i=0; i<3; i++){
            // console.log(i);     // 0 1 2
            function test() {
                console.log(i);   // 2
            }
        }
        test();
        // console.log(i);   // Uncaught ReferenceError: i is not defined

        // var list = [];
        // // 这里的i是全局变量
        // for(var i = 0; i < 3; i++){     // 0 1 2 3
        //     var fn = function test() {
        //         console.log(i);         // 3
        //     };
        //     // 将函数添加到列表中
        //     list.push(fn);
        // }
        // // console.log(i);      // 3
        // // console.log(list);   // 三个函数
        // list[0]();    // 3
        // list[1]();    // 3
        // list[2]();    // 3

        var list = [];
        // 这里的i是局部变量
        // 注意点: 由于i是局部变量, 所以每次执行完循环体,都会重新定义一个i变量
        for(let i = 0; i < 3; i++){     // 0 1 2 3
            var fn = function test() {
                console.log(i);         // 3
            };
            // 将函数添加到列表中
            list.push(fn);
        }
        // console.log(i);      // 3
        // console.log(list);
        list[0]();    // 0
        list[1]();    // 1
        list[2]();    // 2

        for(let i = 0; i < 3; i++){     // 0 1 2 3
            // 注意点: 在ES6中由于{}是块级作用域, 所以只要在块级作用域中定义了一个函数
            //         并且这个函数中用到了块级作用域中的数据, 那么这个函数就是闭包
            function test() {
                console.log(i);         // 2
            }
        }
        test();   // 2

闭包 + 索引同步 练习2:

<body>
    <button>我是按钮1</button>
    <button>我是按钮2</button>
    <button>我是按钮3</button>

    <script>

        // 在ES6中
        // 1.for循环中通过let定义的变量是一个局部变量
        // 2.for循环中通过let定义的变量每次执行循环体都会重新定义一个新的
        //   也就是每个循环体都有一个属于自己的变量
        // 3.for循环中如果定义了函数, 这个函数用到了通过let定义的变量, 那么这个函数是一个闭包

        // 获取元素
        let oButtons = document.querySelectorAll("button");
        // 遍历数组元素
        for(let i=0; i<oButtons.length; i++){
            // 获取button元素
            let button = oButtons[i];
            // 绑定点击事件
            button.onclick = function (){
                console.log(i);
            }
        }
    </script>
</body>

9.排他思想

  • 什么是排他思想
    • 清除其它非选中元素的样式, 只设置当前选中元素样式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>排他思想</title>
    <style>
        ul{
            width: 300px;
            border: 1px solid black; 
            margin: 200px auto;
        }
        ul>li{
            border: 1px solid pink;
            height: 30px;
            line-height: 30px;
        }
        .current{
            background-color: pink;
        }

    </style>
</head>
<body>

    <ul>
        <li>我是第一个li</li>
        <li>我是第二个li</li>
        <li>我是第三个li</li>
        <li>我是第四个li</li>
        <li>我是第五个li</li>
    </ul>

    <script>
        // 1.什么是排它思想 ?
        //   清除其它非选中元素的样式, 只设置当前选中元素样式

        // 获取元素列表
        let oList = document.querySelectorAll("ul>li");
        // console.log(oList);

        // 保存上一次元素索引
        let preIndex = 0


        // 方式1:通过 let 定义变量
        // 遍历元素列表
        for(let i=0; i<oList.length; i++){
            // 获取元素
            let item = oList[i];
            // 绑定点击事件
            item.onclick = function (){

                // 排它(先清理掉所有元素的样式,再重新设置选中元素样式)
                // 但是这样很消耗性能,实质上只需要将上一个元素的样式清空即可
                // for(let j = 0; j < oItems.length; j++){
                //     let li = oItems[j];
                //     li.className = "";
                // }

                // 清理上一个元素样式
                let preItem = oList[preIndex];
                preItem.className = "";
                // 设置当前元素样式
                this.className = "current";
                preIndex = i;
            }
        }


        // 方式2:通过 var 定义变量
        // 遍历元素列表
        for (var i = 0; i < oList.length; i++) {
            // 获取元素
            let item = oList[i];
            (function (index){
                // 绑定点击事件
                item.onclick = function () {
                    // 清理上一个元素样式
                    let preItem = oList[preIndex];
                    preItem.className = "";
                    // 设置当前元素样式
                    this.className = "current";
                    preIndex = index;
                }
            })(i)
        }
    </script>

</body>
</html>

10.Tab选项卡-面向对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tab选项卡-面向对象</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #tab{
            width: 400px;
            height: 300px;
            border: 1px solid #000;
            margin: 100px auto;
        }
        #tab_top{
            list-style: none;
            width: 100%;
            height: 50px;
            line-height: 50px;
            text-align: center;
            display: flex;
            justify-content: space-between;
        }
        #tab_top>li{
            width: 80px;
            height: 100%;
            background: skyblue;
            border-right: 1px solid #ccc;
        }
        #tab_top>li:last-child{
            border-right: none;
        }
        #tab_bottom{
            width: 100%;
            height: 250px;
        }
        #tab_bottom>.tab-content{
            width: 100%;
            height: 100%;
            display: none;
        }
        .selected{
            background: red !important;
        }
    </style>
</head>
<body>
    <!--
        在前端开发中如果id名称是由多个单词组成的, 那么建议使用下划线来连接
        在前端开发中如果class名称是由多个单词组成的, 那么建议使用中划线来连接
    -->
    <div id="tab">
        <ul id="tab_top">
            <li class="tab-item selected">新闻</li>
            <li class="tab-item">视频</li>
            <li class="tab-item">音乐</li>
            <li class="tab-item">军事</li>
            <li class="tab-item">财经</li>
        </ul>
        <div id="tab_bottom">
            <div class="tab-content">新闻的内容</div>
            <div class="tab-content">视频的内容</div>
            <div class="tab-content">音乐的内容</div>
            <div class="tab-content">军事的内容</div>
            <div class="tab-content">财经的内容</div>
        </div>
    </div>

    <script>

        // 面向过程  //
        // // 1.获取元素
        // let oItems = document.querySelectorAll("ul>li");
        // let oDivs = document.querySelectorAll(".content");
        // // 2.保存上一个设置样式的元素索引
        // let previousIndex = 0;
        // // 3.遍历列表元素
        // for (let currentIndex = 0; currentIndex < oItems.length; currentIndex++) {
        //     let item = oItems[currentIndex];
        //     // 4.绑定点击事件
        //     item.onclick = function change() {
        //         // 4.1 清空上一个元素的样式
        //         // 修改列表背景颜色
        //         let preItem = oItems[previousIndex];
        //         preItem.className = "";
        //         // 修改div元素的display属性
        //         let preDiv = oDivs[previousIndex];
        //         preDiv.style.display = "none";
                
        //         // 4.2 设置当前点击元素的样式
        //         this.className = "current";
        //         let currentDiv = oDivs[currentIndex];
        //         currentDiv.style.display = "block";

        //         // 4.3 保存当前索引
        //         previousIndex = currentIndex;

        //     }
        // }


        // 面向对象  //
        // 定义Tab类
        class Tab{
            // 构造函数
            constructor(){
                // 将获取的元素定义为Tab类的属性
                this.tabItem = document.querySelectorAll(".tab-item");
                this.tabContent = document.querySelectorAll(".tab-content");
                this.previousIndex = 0;
                // 设置默认选中的第一个tabContent的样式
                this.tabContent[0].style.display = "block";
            }
            // 定义添加点击事件(修改对应元素的样式)方法
            addClickEvent(){
                // 遍历tabItem元素类表
                for(let i=0; i<this.tabItem.length; i++){
                    let item = this.tabItem[i];
                    // 绑定点击事件
                    //  item.onclick = function(){      // console.log(this);   // item
                    item.onclick = () => {
                        // console.log(this);      // Tab对象
                        // 1.清空上一个元素样式(排他思想)
                        let preItem = this.tabItem[this.previousIndex];
                        // preItem.className = "";
                        // 因为有两个类名,只需将第二个类名selected置空即可
                        preTabItem.className = preTabItem.className.replace("selected", "");
                        let precontent = this.tabContent[this.previousIndex];
                        precontent.style.display = "none";

                        // 2.设置当前点击元素样式
                        let currentItem = this.tabItem[i];
                        // currentItem.className = "selected";
                        currentItem.className = preTabItem.className + "selected";
                        let currentContent = this.tabContent[i];
                        currentContent.style.display = "block";

                        // 3.保存当前索引
                        this.previousIndex = i;
                    }
                }
            }
        }
        let table = new Tab();
        table.addClickEvent();
    </script>
</body>
</html>

11.全选-反选

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>全选反选</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .music{
            /* border: 1px solid black; */
            /* 水平阴影的位置  垂直阴影的位置  阴影的大小  阴影的颜色*/
            box-shadow: 0 0 5px #000;
            width: 400px;
            margin: 200px auto;

            padding-left: 20px;
            padding-right: 20px;
            box-sizing: border-box;
        }
        .music>h3{
            line-height: 40px;
            text-align: center;
            border-bottom: 1px solid #ccc;
            /* margin-left: 20px;
            margin-right: 20px; */
        }
        .music>ul{
            list-style: none;
        }
        .music>ul>li{
            border-bottom: 1px solid #ccc;
            /* margin-left: 20px;
            margin-right: 20px; */

        }
        .music>div{
            line-height: 40px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="music">
        <h3>歌曲排行榜</h3>
        <ul>
            <li><input type="checkbox">醒着做梦</li>
            <li><input type="checkbox">男人不应该让女人流泪</li>
            <li><input type="checkbox">女人不应该让男人太累</li>
            <li><input type="checkbox">狂浪</li>
            <li><input type="checkbox">生僻字</li>
            <li><input type="checkbox">沙漠骆驼</li>
            <li><input type="checkbox">最美的期待</li>
            <li><input type="checkbox">光年之外</li>
        </ul>
        <div>
            <button id="all_select">全选</button>
            <button id="cancel_select">取消全选</button>
            <button id="reverse_select">反选</button>
        </div>
    </div>

    <script>
        // 1.获取元素
        let oItems = document.querySelectorAll("input");
        let allSelectButton = document.querySelector("#all_select");
        let cancelSelectButton = document.querySelector("#cancel_select");
        let reverseSelectButton = document.querySelector("#reverse_select");

        // 2.监听全选按钮
        allSelectButton.onclick = function(){
            oItems.forEach(function (item){
                // 在JS中,如果HTML标签的属性名称和取值名称一样时, 那么JS就会返回true
                // item.checked = "checked";    // checked="checked"  true 
                // console.log(item.checked);   // 默认为false
                item.checked = true;
            });
        }
        // 3.监听取消全选按钮
        cancelSelectButton.onclick = function () {
            oItems.forEach(function (item) {
                // item.checked = "";
                item.checked = false;
            });
        }
        // 4.监听反选按钮
        reverseSelectButton.onclick = function () {
            oItems.forEach(function (item) {
                item.checked = !item.checked ;
            });
        }
    </script>

</body>
</html>

12.Date 时间对象

(1).获取当前时间

        let date = new Date();
        console.log(date);

(2).获取当前时间距离世界标准时间(1970年1月1日)的毫秒

  • Date.now()

  • valueOf()

        console.log(Date.now());
        let date = new Date();
        console.log(date.valueOf());  

(3).创建指定时间

  • 整体传入
  • 单独传入(注意点:如果月份是单独传入的,那么会多一个月!)
        let date1 = new Date("2021-6-10 15:23:09")
        console.log(date1);  
        // 注意点: 在创建指定时间的时候, 如果月份是单独传入的, 那么会多一个月!
        let date2 = new Date(2021, 5, 10, 15, 23, 9);  
        console.log(date2);   

(4).获取指定时间年月日时分秒

  • getFullYear()                 # 年

  • getMonth()                   # 月            (注意:通过该方法获取到的月份会少一个月!)

  • getDate()                     # 日

  • getHours()                  # 时

  • getMinutes()               # 分

  • getSeconds()             # 秒

        let date = new Date();
        console.log(date);
        console.log(date.getFullYear());
        // 注意点; 通过getMonth方法获取到的月份会少一个月!
        console.log(date.getMonth()+1);
        console.log(date.getDate());
        console.log(date.getHours());
        console.log(date.getMinutes());
        console.log(date.getSeconds());

(5).时间格式化

  • 符合中国人习惯的时间展示方式:2021-6-10 15:39:10
        let date = new Date();
        // 定义时间格式化函数
        // 2021-6-10 15:39:10
        function formartDate(date){
            return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
        }
        // 调用时间格式化函数
        let res = formartDate(date)
        console.log(res);

13.Date 时间对象-计算时间差值

  • 需求:计算以下两个时间之间的差值
        /*
           1秒 = 1000毫秒   1分钟 = 60秒    1小时 = 60分钟   1天 = 24小时
        */

        // 需求:计算以下两个时间之间的差值(10天1小时29分40秒)
        let curDate = new Date("2020-4-19 22:30:20");
        let remDate = new Date("2020-4-30 00:00:00");

        // 1.得到两个时间之间的差值(毫秒)
        let differTime = remDate - curDate;
        // let differTime = remDate.valueOf() - curDate.valueOf();
        console.log(differTime);

        // 2.得到两个时间之间的差值(秒)
        let differSecond = differTime / 1000;

        // 3.得到两个时间相差的天数(相差的天数 = 相差的总秒数 / 每一天的秒数)
        let day = parseInt(differSecond / (60 * 60 * 24));
        console.log(day);

        // 4.得到两个时间相差的小时(相差的小时 = 相差的总秒数 / 小时 % 24)
        let hour = parseInt(differSecond / (60 * 60) % 24);
        console.log(hour);

        // 5.得到两个时间相差的分钟(相差的分钟 = 相差的总秒数 / 分钟 % 60)
        let minute = parseInt(differSecond / 60 % 60);
        console.log(minute);
        
        // 6.得到两个时间相差的秒数(相差的秒数 = 相差的总秒数 % 60)
        let second = parseInt(differSecond % 60);
        console.log(second);

14.秒杀效果

  • 秒杀效果:实质上就是 当前时间 距离 未来时间 的差值
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="fonts/iconfont.css">
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            width: 190px;
            height: 270px;
            /* border: 1px solid red; */
            background-color: red;
            margin: 100px auto;
            text-align: center;
            color: white;
            /* box-sizing: border-box; */
        }
        .box>h3{
            font-size: 26px;
            padding-top: 30px;
        }
        /* 第一个p标签 */
        .box>p:nth-of-type(1){
            color: rgba(255,255,255,0.5);
            margin-top: 5px;
        }
        .box>i{
            font-size: 40px;
            display: inline-block;
            margin-top: 20px;
            margin-bottom: 20px;
        }        

        .box>.time{
            /* 弹性定位 */
            display: flex;
            /* 两端留白,居中对齐 */
            /* justify-content: center; */
            /* 两端对齐,元素之间的间隔都相等 */
            justify-content: space-between;
            margin: 10px auto;
            border: 1px solid green;
            width: 140px;
            box-sizing: border-box;
        }

        .box>.time>div{
            width: 40px;
            height: 40px;
            line-height: 40px;
            /* border: 1px solid black; */
            background: #333;
            font-weight: bold;
            position: relative;
        }

        /* 伪元素::before  可用于在元素内容之前插入一些内容 */
        .time>div::before{
            content: "";
            display: block;
            width: 100%;
            height: 2px;
            background: #d00;
            /* 子绝父相 */
            position: absolute;
            left: 0;
            top: 50%;
            /* 垂直居中 */
            transform: translateY(-50%);
        }

    </style>
</head>
<body>
    <div class="box"> 
        <h3>京东秒杀</h3>
        <p>FLASH DEALS</p>
        <i class="iconfont icon-lightningbshandian"></i>
        <p>本场距离结束还剩</p>
        <div class="time">
            <div class="hour">00</div>
            <div class="minute">00</div>
            <div class="second">00</div>
        </div>
    </div>

    <script>
        // 秒杀本质:当前时间 距离 未来时间 的差值
        // 1.获取元素
        let oHour = document.querySelector(".hour");
        let oMinute = document.querySelector(".minute");
        let oSecond = document.querySelector(".second");

        // 2.设置未来时间
        let remDate = new Date("2021-6-11 12:00:00");

        // 3.定义计算时间差函数
        // console.log(getDifferTime(remDate));
        function getDifferTime(remDate, curDate=new Date()){
            // 1.得到两个时间之间的差值(毫秒)
            let differTime = remDate - curDate;
            // 2.得到两个时间之间的差值(秒)
            let differSecond = differTime / 1000;
            // 3.得到两个时间相差的天数(相差的天数 = 相差的总秒数 / 每一天的秒数)
            let day = parseInt(differSecond / (60 * 60 * 24));
            // 如果不足两位数,则用0补齐!
            day = day >=10 ? day : "0" + day;
            // 4.得到两个时间相差的小时(相差的小时 = 相差的总秒数 / 小时 % 24)
            let hour = parseInt(differSecond / (60 * 60) % 24);
            hour = hour >= 10 ? dhoury : "0" + hour;
            // 5.得到两个时间相差的分钟(相差的分钟 = 相差的总秒数 / 分钟 % 60)
            let minute = parseInt(differSecond / 60 % 60);
            minute = minute >= 10 ? minute : "0" + minute;
            // 6.得到两个时间相差的秒数(相差的秒数 = 相差的总秒数 % 60)
            let second = parseInt(differSecond % 60);
            second = second >= 10 ? second : "0" + second;
            // 以对象的形式返回
            return {
                "day": day,
                "hour": hour,
                "minute": minute,
                "second": second
            }
        }

        // 4.定义设置时间函数
        function setTime(remDate){
            let diffTime = getDifferTime(remDate);
            // 将获得的差值设置为对应的div元素
            oHour.innerText = diffTime.hour;
            oMinute.innerText = diffTime.minute;
            oSecond.innerText = diffTime.second;
        }
        // 需要先调用一次,否则进入后会看到初始时间是 00:00:00
        setTime(remDate);

        // 5.设置定时器,每秒重新设置一次时间
        setInterval(() => {
            setTime(remDate);
        }, 1000);
        
    </script>
</body>
</html>

15.时钟效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style> 
        *{
            padding: 0;
            margin: 0;
        }
        .clock{
            /* 必须设置宽度和高度,且大于背景图片的尺寸,这样图片才能完全显示出来 */
            width: 300px;
            height: 600px;
            margin: 100px auto;
            background-image: url(images/clock.png);
            position: relative;
            /* border: 1px solid red; */
        }
        .clock>.box{
            width: 120px;
            height: 120px;
            /* background-color: pink; */
            /* 子绝父相 */
            position: absolute;
            bottom: 220px;
            /* 左边距为宽度的50%,即盒子的左边框距离父元素盒子150px */
            left: 50%;
            /* 但是盒子本身又有120的宽度,所以还需要右移盒子本身宽度的50%,即60px */
            /* transform: translateX(-60px); */
            transform: translateX(-50%);
            /* 在绝对定位中 margin: 0 auto; 让盒子本身垂直居中对齐 会失效 */
            /* margin: 0 auto; */
        }
        .hour, .minute, .second{
            width: 6px;
            height: 120px;
            /* 子绝父相 */
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
        }
        .clock>.box>.hour{
            background-image: url(images/hour.png);
        }
        .clock>.box>.minute{
            background-image: url(images/minute.png);
        }
        .clock>.box>.second{
            background-image: url(images/second.png);
        }
    </style>
</head>
<body>
    <div class="clock">   
        <div class="box">
            <div class="hour"></div>
            <div class="minute"></div>
            <div class="second"></div>
        </div>
    </div>

    <script>
        // 1.获取元素
        let oHour = document.querySelector(".hour");
        let oMinute = document.querySelector(".minute");
        let oSecond = document.querySelector(".second");

        // 2.定义设置时间函数
        function setTime(){
            // 2.1 获取当前时间
            let currentTime = new Date();
            // 2.2 设置 transform 旋转度数 属性
            //      360 度 / 12 小时 = 30 度      (一个小时旋转30度)
            oHour.style.transform =  `rotate(${currentTime.getHours() * 30}deg)`;
            //      360 度 / 12 * 5 分钟 / 6 度   (一个分钟旋转6度)
            oMinute.style.transform = `rotate(${currentTime.getMinutes() * 6}deg)`;
            //      360 度 / 60 秒 = 6 度         (一个秒钟旋转6度)
            oSecond.style.transform = `rotate(${currentTime.getSeconds() * 6}deg)`;
        }

        console.log(new Date());
        setTime();
        // 3.设置定时器,每隔1秒钟重新设置时间
        setInterval(() => {
            setTime();
        }, 1000);
        
    </script>
</body>
</html>

16.长图效果

17.匀速动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>匀速动画</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    
        .box {
            width: 100px;
            height: 100px;
            background: red;
        }
    
        .line1, .line2 {
            width: 500px;
            height: 20px;
            background: blue;
        }
    
        .line2 {
            width: 200px;
            background: purple;
        }
    </style>
</head>
<body>
    <button id="start1">开始到500</button>
    <button id="start2">开始到200</button>
    <button id="end">结束</button>
    <div class="box"></div>
    <div class="line1"></div>
    <div class="line2"></div>

    <script>
        // 1.获取元素
        let startBtn1 = document.querySelector("#start1");
        let startBtn2 = document.querySelector("#start2");
        let endBtn = document.querySelector("#end");
        let oDiv = document.querySelector(".box");

        // // 2.绑定点击事件
        // let timer1 = null;
        // startBtn1.onclick = function(){
        //     // 当再次点击按钮时,关闭上一次的定时器!
        //     clearInterval(timer1);
        //     // 3.记录终点位置
        //     let target = 500;
        //     // 4.设置定时器
        //     timer1 = setInterval(() => {
        //         // 4.1 获取当前元素位置
        //         // 初始位置是由css设置的,oDiv.style.marginLeft方式无法获取,所以需要单独设置一个0
        //         let curposition = parseInt(oDiv.style.marginLeft) || 0;
        //         // let curposition = parseInt(getComputedStyle(oDiv).marginLeft);
        //         // 4.2 设置步长
        //         let step = 11;
        //         // 4.3 计算新的位置
        //         curposition += step;
        //         console.log(target - curposition, step);
        //         // 4.4 判断是否超过终点位置
        //         // if(curposition >= target){
        //         if (Math.abs(target - curposition) <= Math.abs(step)) {
        //             clearInterval(timer1);
        //             // 当target/step步长为小数时,默认偏移量就会多出一点,所以当它大于500后,需要手动复位到最大偏移量即可,
        //             curposition = target;
        //         }
        //         // 4.5 重新设置元素的位置
        //         oDiv.style.marginLeft = curposition + "px";
        //     }, 100);
        // }

        // let timer2 = null;
        // startBtn2.onclick = function () {
        //     // 当再次点击按钮时,关闭上一次的定时器!
        //     clearInterval(timer2);
        //     // 3.记录终点位置
        //     let target = 200;
        //     // 4.设置定时器
        //     timer2 = setInterval(() => {
        //         // 4.1 获取当前元素位置
        //         // 初始位置是由css设置的,oDiv.style.marginLeft方式无法获取,所以需要单独设置一个0
        //         let curposition = parseInt(oDiv.style.marginLeft) || 0;
        //         // let curposition = parseInt(getComputedStyle(oDiv).marginLeft);
        //         // 4.2 设置步长
        //         let step = -11;
        //         // 4.3 计算新的位置
        //         curposition += step;
        //         // 4.4 判断是否超过终点位置
        //         console.log(Math.abs(target - curposition), Math.abs(step));
        //         // if(begin >= target){
        //         if (Math.abs(target - curposition) <= Math.abs(step)) {
        //             clearInterval(timer2);
        //             // 当target/step步长为小数时,默认偏移量就会多出一点,所以当它大于500后,需要手动复位到最大偏移量即可,
        //             curposition = target;
        //         }
        //         // 4.5 重新设置元素的位置
        //         oDiv.style.marginLeft = curposition + "px";
        //     }, 100);
        // }

        // endBtn.onclick = function () {
        //     clearInterval(timer1);
        //     clearInterval(timer2);
        // }
        

        let timer = null;
        // 两个按钮绑定的事件只是 target终点位置 与 step步长 不同而已
        startBtn1.onclick = function (){
            linearAnimation(oDiv, 500);
        }
        startBtn2.onclick = function () {
                linearAnimation(oDiv, 200);
        }
        endBtn.onclick = function () {
            clearInterval(timer);
        }

        // 将匀速移动封装为一个函数!
        function linearAnimation(ele, target) {
                // 当再次点击按钮时,关闭上一次的定时器!
                clearInterval(timer);
                // 4.设置定时器
                timer = setInterval(() => {
                    // 4.1 获取当前元素位置
                    // 初始位置是由css设置的,oDiv.style.marginLeft方式无法获取,所以需要单独设置一个0
                    let curposition = parseInt(ele.style.marginLeft) || 0;
                    // let curposition = parseInt(getComputedStyle(oDiv).marginLeft);
                    // 4.2 设置步长
                    //   0  -  500 = -500     13
                    //   500 -  200 = 300    -13
                    let step = (curposition - target) > 0 ? -13 : 13;
                    // 4.3 计算新的位置
                    curposition += step;
                    console.log(target - curposition, step);
                    // 4.4 判断是否超过终点位置
                    // if(curposition >= target){
                    if (Math.abs(target - curposition) <= Math.abs(step)) {
                        clearInterval(timer);
                        // 当target/step步长为小数时,默认偏移量就会多出一点,所以当它大于500后,需要手动复位到最大偏移量即可,
                        curposition = target;
                    }
                    // 4.5 重新设置元素的位置
                    oDiv.style.marginLeft = curposition + "px";
                }, 100);
            }
        
    </script>
</body>
</html>

18.缓动动画

 

19.轮播图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>轮播图</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        .box{
            width: 670px;
            height: 300px;
            border: 1px solid skyblue;
            margin: 100px auto;
            position: relative;
            overflow: hidden;
        }
        ul{
            list-style: none;
            display: flex;
        }
        p{
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            /*border: 1px solid yellowgreen;*/
            /* 一定要设置宽度 */
            width: 100%;
            /* 弹性定位 */
            display: flex;
            /* 两端对齐,中间空隙相等*/
            justify-content: space-between;
        }
        p>span{
            width: 30px;
            height: 60px;
            background: rgba(0,0,0,0.5);
            font-size: 40px;
            color: #fff;
            text-align: center;
            line-height: 60px;
        }
    </style>
</head>
<body>
    <div class="box">
        <ul>
            <li><img src="images/ad1.jpg"></li>
            <li><img src="images/ad2.jpg"></li>
            <li><img src="images/ad3.jpg"></li>
        </ul>
        <p>
            <span class="left">&lt</span>
            <span class="right">&gt</span>
        </p>
    </div>
    <script>
        // 1.获取元素
        let oLeft = document.querySelector(".left");
        let oRight = document.querySelector(".right");
        let oUl = document.querySelector("ul");
        let oItems = document.querySelectorAll("ul>li");
        let imgWidth = parseFloat(getComputedStyle(oItems[0]).width);

        // 2.绑定点击事件
        let currentIndex = 0;
        oRight.onclick = function () {
            currentIndex++;
            // 当滑动到最后一张图片,就将currentIndex置为 0
            if(currentIndex > oItems.length-1){
                currentIndex = 0;
            }
            // oUl.style.marginLeft = -(imgWidth * currentIndex) + "px";

            // 调用动画函数
            // linearAnimation(oUl, -(imgWidth * currentIndex));
            easeAnimation(oUl, -(imgWidth * currentIndex));
        };
        oLeft.onclick = function () {
            currentIndex--;
            // 当滑动到第一张图片,就将currentIndex置为 长度-1
            if(currentIndex < 0){
                currentIndex = oItems.length-1;
            }
            // oUl.style.marginLeft = -(imgWidth * currentIndex) + "px";

            // 调用动画函数
            // linearAnimation(oUl, -(imgWidth * currentIndex));
            easeAnimation(oUl, -(imgWidth * currentIndex));
        };


        let timerId = null;
        //  匀速动画
        function linearAnimation(ele, target) {
            clearInterval(timerId);
            timerId = setInterval(function () {
                // 1.拿到元素当前的位置
                let begin = parseInt(ele.style.marginLeft) || 0;
                // 2.定义变量记录步长
                //         0  -  500 = -500    13
                //         500 -  200 = 300    -13
                let step = (begin - target) > 0 ? -13 : 13;
                // 3.计算新的位置
                begin += step;
                console.log(Math.abs(target - begin), Math.abs(step));
                if(Math.abs(target - begin) <= Math.abs(step)){
                    clearInterval(timerId);
                    begin = target;
                }

                // 4.重新设置元素的位置
                ele.style.marginLeft = begin + "px";
            }, 100);
        }
        // 缓速动画
        function easeAnimation(ele, target) {
            clearInterval(timerId);
            timerId = setInterval(function () {
                // 1.拿到元素当前的位置
                let begin = parseInt(ele.style.marginLeft) || 0;
                // 2.定义变量记录步长
                // 公式: (结束位置 - 开始位置) * 缓动系数(0 ~1)
                let step = (target - begin) * 0.3;
                console.log(step);
                // 3.计算新的位置
                begin += step;
                if (Math.abs(Math.floor(step)) <= 1) {
                    clearInterval(timerId);
                    begin = target;
                }
                // 4.重新设置元素的位置
                ele.style.marginLeft = begin + "px";
            }, 100);
        }
    // 存在的问题:按下oRight,图片列表会整体左移,当移动到最后一张图片时,再按键时会发现不会平滑的向左移动
    // 同理可知,按下oLeft,图片列表会整体右移,当移动到第一张图片时,再按键时会发现不会平滑的向右移动
    </script>
</body>
</html>

20.无限轮播图

思路:在最后一张图片后面再添加第一张图片,当移动到最后一张/第一张时,快速跳转至第一张/最后一张即可

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>无限轮播图</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        .box{
            width: 670px;
            height: 300px;
            border: 1px solid skyblue;
            margin: 100px auto;
            position: relative;
            overflow: hidden;
        }
        ul{
            list-style: none;
            display: flex;
        }
        p{
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            /*border: 1px solid yellowgreen;*/
            /* 一定要设置宽度 */
            width: 100%;
            /* 弹性定位 */
            display: flex;
            /* 两端对齐,中间空隙相等*/
            justify-content: space-between;
        }
        p>span{
            width: 30px;
            height: 60px;
            background: rgba(0,0,0,0.5);
            font-size: 40px;
            color: #fff;
            text-align: center;
            line-height: 60px;
        }
    </style>
</head>
<body>
<div class="box">
    <ul>
        <li><img src="images/ad1.jpg"></li>
        <li><img src="images/ad2.jpg"></li>
        <li><img src="images/ad3.jpg"></li>

        <!--  在最后一张图片添加第一张图片! -->
        <li><img src="images/ad1.jpg"></li>
    </ul>
    <p>
        <span class="left">&lt</span>
        <span class="right">&gt</span>
    </p>
</div>
<script>
    // 1.获取元素
    let oLeft = document.querySelector(".left");
    let oRight = document.querySelector(".right");
    let oUl = document.querySelector("ul");
    let oItems = document.querySelectorAll("ul>li");
    let imgWidth = parseFloat(getComputedStyle(oItems[0]).width);

    // 2.绑定点击事件
    let currentIndex = 0;
    oRight.onclick = function () {
        currentIndex++;
        // 当滑动到最后一张图片,就将currentIndex置为 0
        if(currentIndex > oItems.length-1){
            currentIndex = 0;
            // 快速的跳转到第一张 !
            oUl.style.marginLeft = -currentIndex * imgWidth + "px";
            currentIndex++;
        }
        // oUl.style.marginLeft = -(imgWidth * currentIndex) + "px";

        // 调用动画函数
        // linearAnimation(oUl, -(imgWidth * currentIndex));
        easeAnimation(oUl, -(imgWidth * currentIndex));
    };
    oLeft.onclick = function () {
        currentIndex--;
        // 当滑动到第一张图片,就将currentIndex置为 长度-1
        if(currentIndex < 0){
            currentIndex = oItems.length-1;
            // 快速的跳转到最后一张 !
            oUl.style.marginLeft = -(imgWidth * currentIndex) + "px";
            currentIndex--;
        }
        // oUl.style.marginLeft = -(imgWidth * currentIndex) + "px";

        // 调用动画函数
        // linearAnimation(oUl, -(imgWidth * currentIndex));
        easeAnimation(oUl, -(imgWidth * currentIndex));
    };


    let timerId = null;
    //  匀速动画
    function linearAnimation(ele, target) {
        clearInterval(timerId);
        timerId = setInterval(function () {
            // 1.拿到元素当前的位置
            let begin = parseInt(ele.style.marginLeft) || 0;
            // 2.定义变量记录步长
            //         0  -  500 = -500    13
            //         500 -  200 = 300    -13
            let step = (begin - target) > 0 ? -13 : 13;
            // 3.计算新的位置
            begin += step;
            console.log(Math.abs(target - begin), Math.abs(step));
            if(Math.abs(target - begin) <= Math.abs(step)){
                clearInterval(timerId);
                begin = target;
            }

            // 4.重新设置元素的位置
            ele.style.marginLeft = begin + "px";
        }, 100);
    }
    // 缓速动画
    function easeAnimation(ele, target) {
        clearInterval(timerId);
        timerId = setInterval(function () {
            // 1.拿到元素当前的位置
            let begin = parseInt(ele.style.marginLeft) || 0;
            // 2.定义变量记录步长
            // 公式: (结束位置 - 开始位置) * 缓动系数(0 ~1)
            let step = (target - begin) * 0.3;
            console.log(step);
            // 3.计算新的位置
            begin += step;
            if (Math.abs(Math.floor(step)) <= 1) {
                clearInterval(timerId);
                begin = target;
            }
            // 4.重新设置元素的位置
            ele.style.marginLeft = begin + "px";
        }, 100);
    }
</script>
</body>
</html>

21.自动轮播图

    // 1.设置定时器
    let id = setInterval(function () {
        // 调用点击事件函数
        oLeft.onclick();
    },2000);
    // 2.监听鼠标移入事件
    oBox.onmouseenter = function(){
        // 关闭定时器
        clearInterval(id);
    };
    // 3.监听鼠标移出事件
    oBox.onmouseleave = function(){
        // 重新开启定时器
        id = setInterval(function () {
            oLeft.onclick();
        },2000);
    };

22.匀速动画-加强版

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>匀速动画</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .box {
            width: 100px;
            height: 100px;
            background: red;
        }

        .line1,
        .line2 {
            width: 500px;
            height: 20px;
            background: blue;
        }

        .line2 {
            width: 200px;
            background: purple;
        }
    </style>
</head>

<body>
    <button id="start1">开始到500</button>
    <button id="start2">开始到200</button>
    <button id="end">结束</button>
    <div class="box"></div>
    <div class="line1"></div>
    <div class="line2"></div>

    <script>
        // 1.获取元素
        let startBtn1 = document.querySelector("#start1");
        let startBtn2 = document.querySelector("#start2");
        let endBtn = document.querySelector("#end");
        let oDiv = document.querySelector(".box");

        let timer = null;
        // 3.绑定点击事件(两个按钮绑定的事件只是 target终点位置 与 step步长 不同而已)
        startBtn1.onclick = function () {
            // linearAnimation(oDiv, "width", 500);
            // linearAnimation(oDiv, "marginLeft", 500);
            // linearAnimation(oDiv, "marginTop", 500);

            // linearAnimation(oDiv, {"marginTop": 500, "marginLeft": 300}, function(){
            //     alert("动画执行完毕之后,执行的其他操作");
            // });
            linearAnimation(oDiv, { "marginTop": 500, "marginLeft": 300 });
        }
        startBtn2.onclick = function () {
            // linearAnimation(oDiv, "width", 200);
            // linearAnimation(oDiv, "marginLeft", 500);
            // linearAnimation(oDiv, "marginTop", 500);
        }
        endBtn.onclick = function () {
            clearInterval(timer);
        }
        

        // 2.将匀速动画封装为一个函数!
        // 改进点1:如果想让动画水平(marginLeft)、垂直(marginTop)移动或者让高度(width)执行动画,每次都需要修改函数内部封装好的代码,这样很不方便
        // 优化:直接给函数再添加一个attr参数,用于指定执行动画元素的属性,此时直接修改调用函数的参数即可实现水平、垂直、宽度动画
        // function linearAnimation(ele, attr, target) {
            
        // 需求: 多个属性 同时 执行动画
        function linearAnimation(ele, obj, fn) {
            // 当再次点击按钮时,关闭上一次的定时器!
            clearInterval(timer);
            // 设置定时器
            timer = setInterval(() => {

                // 用于标记是否 所有属性 都执行完了动画
                let flag = true;

                for (let key in obj) {
                    let attr = key;
                    let target = obj[key];

                    // 2.1 获取当前元素位置
                    // 初始位置是由css设置的,oDiv.style.marginLeft方式无法获取,所以需要单独设置一个0
                    // let begin = parseInt(ele.style.marginLeft) || 0;           // 水平向右移动
                    // let begin = parseInt(getComputedStyle(oDiv).marginLeft);
                    // let begin = parseInt(ele.style.marginTop) || 0;            // 垂直向下移动
                    // let begin = parseInt(getComputedStyle(oDiv).width);        // 从当前宽度开始执行动画

                    let style = getComputedStyle(ele);
                    // let begin = parseInt(style.width);
                    // let begin = parseInt(style["width"]);
                    let begin = parseInt(style[attr]);

                    // 2.2 设置步长
                    //   0  -  500 = -500     13
                    //   500 -  200 = 300    -13
                    let step = (begin - target) > 0 ? -13 : 13;
                    // 2.3 计算新的位置
                    begin += step;
                    // console.log(target - begin, step);

                    // 2.4 判断是否超过终点位置
                    // if(begin >= target){
                    // if (Math.abs(target - begin) <= Math.abs(step)) {
                    //     clearInterval(timer);
                    //     // 当target/step步长为小数时,默认偏移量就会多出一点,所以当它大于500后,需要手动复位到最大偏移量即可,
                    //     begin = target;
                    // }
                    if (Math.abs(target - begin) > Math.abs(step)) {
                        // 如果动画没有执行完就将flag变量置为false
                        flag = false;
                    }
                    else{
                        // 当target/step步长为小数时,默认偏移量就会多出一点,所以当它大于500后,需要手动复位到最大偏移量即可,
                        begin = target;
                    }

                    // 2.5 重新设置元素的位置
                    // ele.style.marginLeft = begin + "px";
                    // ele.style.marginTop =  begin + "px";
                    // ele.style.width = begin + "px";
                    // ele.style["width"] = begin + "px";
                    ele.style[attr] = begin + "px";
                }
                if(flag){
                    // 当所有属性的动画都执行完了,再关闭定时器
                    clearInterval(timer);

                    // fn();

                    // 当动画执行完毕后,如果传递了fn函数则,执行fn函数
                    // if(fn){
                    //     fn();
                    // }
                    
                    // fn为真,则执行fn()
                    fn && fn();
                }
            }, 100);
        }
    </script>
</body>
</html>

23.缓速动画-加强版

    // 缓速动画函数
    function easeAnimation(ele, obj, fn) {
        clearInterval(ele.timerId);
        ele.timerId = setInterval(function () {
            let flag = true;
            for (let key in obj) {
                let target = obj[key];
                // 1.拿到元素当前的位置
                let style = getComputedStyle(ele);
                let begin = parseInt(style[key]) || 0;
                // 2.定义变量记录步长
                // 公式: (结束位置 - 开始位置) * 缓动系数(0 ~1)
                let step = (target - begin) * 0.3;
                // 3.计算新的位置
                begin += step;
                if (Math.abs(Math.floor(step)) > 1) {
                    flag = false;
                } else {
                    begin = target;
                }
                // 4.重新设置元素的位置
                ele.style[key] = begin + "px";
            }
            if (flag) {
                clearInterval(ele.timerId);
                fn && fn();
            }
        }, 100);
    }

24.联动动画-关闭弹窗

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>联动动画-关闭弹窗</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            position: fixed;
            right: 0;
            bottom: 0;
        }
        .top{
            width: 320px;
            height: 302px;
            overflow: hidden;
        }
        .bottom{
            width: 320px;
            height: 102px;
            overflow: hidden;
        }

        span{
            display: inline-block;
            width: 30px;
            height: 30px;
            /* background-color: red; */
            position: absolute;
            right: 0;
            top: 0;
        }
    </style>

</head>
<body>
    <div class="box">
        <div class="top">
            <img src="images/top.jpg">
        </div>
        <div class="bottom">
            <img src="images/bottom.jpg">
        </div>
        <span></span>
    </div>
    
    <!-- 引入js文件(封装了匀速动画、缓速动画函数) -->
    <script src="js/animation2.js"></script>

    <script>
        // 1.获取元素
        let oBoxDiv = document.querySelector(".box");
        let oTopDiv = document.querySelector(".top");
        let oBottomDiv = document.querySelector(".bottom");
        let oCloseBtn = document.querySelector("span");
        
        // 2.绑定点击事件
        oCloseBtn.onclick = function(){
            // 调用 匀速动画 函数 or 缓速动画 函数
            // 参数解释:
            //         ele: 需要执行动画的元素
            //         obj: {key: value}    key:执行动画的属性  value:动画结束时的属性取值
            //         fn:  动画执行完毕之后,需要执行的操作
            // linearAnimation(oTopDiv, { "height": 0 }, function(){
            easeAnimation(oTopDiv, { "height": 0 }, function () {
                // 问题:动画执行的方向不对,因为box的right一直都是0,如果是让oBottomDiv执行动画,那么它会从右至左的移动
                // linearAnimation(oBottomDiv, { "width": 0 }, function() {
                // 改进:直接让整个盒子oBoxDiv的宽度执行动画即可
                easeAnimation(oBoxDiv, { "width": 0 }, function () {
                    // 删除oBoxDiv元素
                    oBoxDiv.parentNode.removeChild(oBoxDiv);
                });
            });
        }
    </script>
</body>
</html>

25.添加事件的三种方式

  • 方式1:通过 onxxx 的方式来添加
  • 注意点:由于是给属性赋值, 所以后赋值的会覆盖先赋值的
        oButton.onclick = function() {
             alert("666");
        }
        oButton.onclick = function () {
                alert("777");
        }
  • 方式2:通过 addEventListener 方法添加
  • 注意点
    • 1.事件名称不需要添加 on
    • 2.后添加的不会覆盖先添加的
    • 3.只支持最新的浏览器 IE9
        oButton.addEventListener("click", function(){
            alert("666");
        })
        oButton.addEventListener("click", function () {
            alert("777");
        })
  • 方式3:通过 attachEvent 方法添加
  • 注意点
    • 1.事件名称必须加上on
    • 2.后添加的不会覆盖先添加的
    • 3.只支持低版本的浏览器
        oButton.attachEvent("onclick", function () {
            alert("666");
        });
        oButton.attachEvent("onclick", function () {
            alert("777");
        });

为了提高浏览器的兼容性,自定义一个函数

        addEvent(oButton, "click", function(){
            alert("666");
        })

        // 为了提高浏览器的兼容性,自定义一个函数
        function addEvent(ele, name, fn) {
            // 如果是低版本的浏览器,则ele.attachEvent存在,就使用attachEvent方法
            if (ele.attachEvent) {
                ele.attachEvent("on" + name, fn);
            }
            // 高版本的浏览器,就使用addEventListener方法
            else {
                ele.addEventListener(name, fn);
            }
        }

26.事件对象

(1).什么是事件对象

  • 事件对象就是一个系统自动创建的一个对象
  • 当注册(绑定)的事件被触发的时候, 系统就会自动创建事件对象

(2).事件对象的注意点

  • 在高级版本的浏览器中, 会自动将事件对象传递给回调函数
  • 在低级版本的浏览器中, 不会自动将事件对象传递给回调函数
  • 在低级版本的浏览器中, 需要通过 window.event 来获取事件对象
    <button id="btn">我是按钮</button>
    <a href="http://www.it666.com">知播渔教育</a>

    <script>
        let oBtn = document.querySelector("#btn");
        oBtn.onclick = function(event){
            // alert("666");
            // console.log(event);
            // 当触发点击事件时,系统就会自动创建事件对象
            // console.log(typeof event);   // object

            // 提高 浏览器兼容性 的写法
            event = event || window.event;
            console.log(event);
        }

        let oA = document.querySelector("a");
        oA.onclick = function (event) {
            alert("666");
            // 阻止默认行为(阻止a链接的页面跳转)
            // 方式1:
            return false;      // 推荐
            // 方式2: 
            // event.preventDefault();     // 只支持高级版本的浏览器
            // event.returnValue = false;  // 只支持低版本IE9以下的浏览器
        }
    </script>

27.事件执行的三个阶段

(1).事件执行的三个阶段

  • 1.1.捕获阶段        (从外向内的传递事件)
  • 1.2.当前目标阶段 (执行回调函数)
  • 1.3.冒泡的阶段    (从内向外的传递事件/抛出事件)

(2).注意点

  • 三个阶段,只有两个会被同时执行, 要么捕获和当前, 要么当前和冒泡

(3).为什么要么只能是捕获和当前, 要么只能是当前和冒泡

  • 这是JS处理事件的历史问题, 早期各大浏览器厂商为占领市场, 以及对事件的理解不同, 后续W3C为了兼容, 将两种方式都纳入标准

       

    <style>
        * {
            margin: 0;
            padding: 0;
        }
        .father {
            width: 300px;
            height: 300px;
            background: red;
        }
        .son {
            width: 150px;
            height: 150px;
            background: blue;
        }
    </style>

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

捕获:(点击子元素)

        let oFDiv = document.querySelector(".father");
        let oSDiv = document.querySelector(".son");

        // true 捕获
        oFDiv.addEventListener("click", function () {
            console.log("father");
        }, true);
        oSDiv.addEventListener("click", function () {
            console.log("son");
        }, true);

冒泡:(点击子元素)

        // false 冒泡
        // oFDiv.addEventListener("click", function () {
        //     console.log("father");
        // }, false);
        // oSDiv.addEventListener("click", function () {
        //     console.log("son");
        // }, false);

        // 冒泡
        oFDiv.onclick = function () {
            console.log("father");
        }
        oSDiv.onclick = function () {
            console.log("son");
        }

事件冒泡-列表选项:

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

<head>
    <meta charset="UTF-8">
    <title>事件冒泡-列表选项</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul {
            list-style: none;
            width: 300px;
            margin: 100px auto;
            border: 1px solid #000;
        }
        .selected {
            background: red;
        }
    </style>
</head>

<body>
    <ul>
        <li class="selected">我是第1个li</li>
        <li>我是第2个li</li>
        <li>我是第3个li</li>
        <li>我是第4个li</li>
        <li>我是第5个li</li>
    </ul>
    <script>
        // 方式1:
        // let oList = document.querySelectorAll("ul>li");
        // // 首先将第一个li设置为currentItem
        // let currentItem = oList[0];
        // for(let item of oList){
        //     item.onclick = fn;
        // }
        // function  fn() {
        //     // 清空上一个元素的背景颜色 (排他思想)
        //     currentItem.className = "";
        //     // 设置当前点击元素的背景颜色
        //     this.className = "selected";
        //     // 保存当前元素
        //     currentItem = this;
        // }

        // 方式2:事件冒泡
        let oUl = document.querySelector("ul");
        // 1.获取第一个li元素,保存到oLi变量中
        let oLi = document.querySelector(".selected");
        oUl.onclick = function(event){
            // 兼容性写法
            event = event || window.event;
            
            // 2.清空上一个元素的背景颜色 (排他思想)
            oLi.className = "";

            // 3.设置当前点击元素的背景颜色
            // console.log(event.target);   // 被点击li元素
            let item = event.target;
            item.className = "selected";

            // 4.保存当前元素
            oLi = item;
        }
    </script>
</body>

</html>

阻止事件冒泡:

    <style>
        * {
            margin: 0;
            padding: 0;
        }
    
        .father {
            width: 300px;
            height: 300px;
            background: red;
        }
    
        .son {
            width: 150px;
            height: 150px;
            background: blue;
        }
    </style>

    <div class="father">
        <div class="son"></div>
    </div>
    <script>
        // 1.拿到需要操作的元素
        var oFDiv = document.getElementById("father");
        var oSDiv = document.getElementById("son");

        // 2.注册(绑定)监听事件
        oFDiv.onclick = function () {
            console.log("father");
        }


        // 默认就是事件冒泡
        // oSDiv.onclick = function () {
        //     console.log("son");
        // }


        // 阻止事件冒泡
        oSDiv.onclick = function (event) {
            // 1.获取事件对象
            event = event || window.event;

            // event.stopPropagation();      // 只支持高级浏览器
            // event.cancelBubble = true;    // 只支持低级浏览器

            // 2.提高 兼容性 的写法
            if (event.cancelBubble) {
                event.cancelBubble = true;
            } else {
                event.stopPropagation();
            }

            console.log("son");
        }
    </script>

移入移出事件的区别:

  • 1.onmouseover 和 onmouseenter 的区别
    • onmouseover   移入到子元素, 父元素的移入事件也会被触发
    • onmouseenter  移入到子元素, 父元素的移入事件不会被触发
  • 2.onmouseout 和 onmouseleave 的区别
    • onmouseout      移出到子元素, 父元素的移入事件也会被触发
    • onmouseleave   移出到子元素, 父元素的移入事件不会被触发
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    
        .father {
            width: 300px;
            height: 300px;
            background: red;
        }
    
        .son {
            width: 150px;
            height: 150px;
            background: blue;
        }
    </style>

    <div class="father">
        <div class="son"></div>
    </div>
        let oFDiv = document.querySelector(".father");
        let oSDiv = document.querySelector(".son");

        // oFDiv.onmouseover = function () {
        //     console.log("father");
        // }
        // oSDiv.onmouseover = function () {
        //     console.log("son");
        // }

        // oFDiv.onmouseenter = function () {
        //     console.log("father");
        // }
        // oSDiv.onmouseenter = function () {
        //     console.log("son");
        // }

        // oFDiv.onmouseout = function () {
        //     console.log("father");
        // }
        // oSDiv.onmouseout = function () {
        //     console.log("son");
        // }

        oFDiv.onmouseleave = function () {
            console.log("father");
        }
        oSDiv.onmouseleave = function () {
            console.log("son");
        }

28.事件位置

  • offsetX / offsetY:事件触发相对于 当前元素 自身的位置
  • clientX / clientY:事件触发相对于 浏览器 可视区域 的位置
    • 注意点:可视区域是不包括滚动出去的范围的
  • pageX / pageY:事件触发相对于 整个网页 的位置
    •  注意点:整个网页包括滚动出去的范围的
  • screenX / screenY:事件触发相对于 屏幕(显示器) 的位置
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件位置获取</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        div {
            width: 100px;
            height: 100px;
            background: red;
            margin-left: 100px;
            margin-top: 800px;
        }
    </style>
</head>
<body>
    <div id="box"></div>
    <script>
        var oDiv = document.getElementById("box");
        oDiv.onclick = function (event) {
            // 获取event事件对象
            event = event || window.event;

            // console.log("offsetX", event.offsetX);
            // console.log("offsetY", event.offsetY);

            // console.log("clientX", event.clientX);
            // console.log("clientY", event.clientY);
            // console.log("----------------------");
            // console.log("pageX", event.pageX);
            // console.log("pageY", event.pageY);

            console.log(event.screenX);
            console.log(event.screenY);
        }
    </script>
</body>
</html>

事件位置-佩奇跟我走:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件位置-佩奇跟我走</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        html, body{
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
    </style>>
</head>
<body>
    <img src="images/pig.gif">

    <script>
        let oImg = document.querySelector("img");
        // 1.获取oImg元素的初始样式
        let style = getComputedStyle(oImg);

        document.body.onmousemove = function(event){
            // 2.获取事件
            event = event || window.event;
            
            // 3.重新设置图片的左外边距与上外边距
            // 此时小猪佩奇确实在跟着鼠标移动,但是鼠标在佩奇的左上角
            // oImg.style.marginLeft = event.clientX + "px";
            // oImg.style.marginTop = event.clientY + "px";

            // 想让鼠标在佩奇的正中心,只需将图片的左外边距再左移佩奇宽度的一半,且将图片的上外边距再上移佩奇高度的一半即可
            // clientX / clientY: 事件触发相对于 浏览器 可视区域 的位置
            oImg.style.marginLeft = event.clientX - parseFloat(style.width)/2 + "px";
            oImg.style.marginTop = event.clientY - parseFloat(style.height)/2 + "px";

            // oImg.style.marginLeft = event.pageX - parseFloat(style.width) / 2 + "px";
            // oImg.style.marginTop = event.pageY - parseFloat(style.height) / 2 + "px";
        }
    </script>
</body>
</html>

29.正则表达式

(1).什么是正则表达式?

  • 正则表达式就是对字符串操作的一种逻辑公式

(2).正则表达式的作用?

  • 2.1 在字符串"查找"是否包含指定子串
  • 2.2 从字符串中"提取"指定子串
  • 2.3 对字符串中指定的内容进行"替换"

在学习正则表达式之前使用的方法:

        // 1.字符串查找
        let str = "123abc456";
        let index = str.indexOf("abc");
        let index = str.lastIndexOf("abc");
        let flag = str.includes("abc");

        // 2.字符串提取
        let str = "123abc456";
        let startIndex = str.indexOf("a");
        console.log(str.substr(startIndex, "abc".length));

        // 3.字符串替换
        let str = "123abc456";
        str.replace("abc", "it666");

1.通过正则表达式,匹配 / 查找字符

  • 需求:查找字符串中是否包含某个字符
  • 1.1 查找字符串中是否包含a/A
        let str = "123abc456";
        // 1.1 创建一个正则表达式对象,并指定匹配的规则
        // 注意点: 默认情况下在正则表达式中是区分大小写的,i:不区分大小写
        let reg = new RegExp("A", "i");
        // 1.2 利用test方法匹配字符串
        let res = reg.test(str);
        console.log(res);   // true

  • 1.2 查找str字符串中是否包含日期
        let str = "abc2020-1-11def";

        // 2.1 通过构造函数创建正则表达式对象
        // \d:匹配数字,第一个\表示转移,即\\表示一个\
        // d{4}:匹配4个数字   d{1,2}:匹配1到2个数字
        // let reg = new RegExp("\\d{4}-\\d{1,2}-\\d{1,2}");

        // 2.2 通过字面量来创建正则表达式对象
        let reg = /\d{4}-\d{1,2}-\d{1,2}/;
        let res = reg.test(str);
        console.log(res);   // true

2.通过正则表达式,提取符合规则的字符串

        let str = "abc2020-1-11def2019-11-11fdjsklf";
        // 注意点:默认情况下在正则表达式中一旦匹配就会停止查找,g:全局匹配
        let reg = /\d{4}-\d{1,2}-\d{1,2}/g;
        let res = str.match(reg);
        console.log(res);
        console.log(res[0]);
        console.log(res[1]);

3.通过正则表达式,替换符合规则的字符串


        let str = "abc2020-1-11def2019-11-11fdjsklf";
        let reg = /\d{4}-\d{1,2}-\d{1,2}/g;
        // replace:替换字符串
        let newStr = str.replace(reg, "it666");
        console.log(str);
        console.log(newStr);

常用正则表达式合集:

验证数字:^[0-9]*$
验证n位的数字:^\d{n}$
验证至少n位数字:^\d{n,}$
验证m-n位的数字:^\d{m,n}$
验证零和非零开头的数字:^(0|[1-9][0-9]*)$
验证有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
验证有1-3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
验证非零的正整数:^\+?[1-9][0-9]*$
验证非零的负整数:^\-[1-9][0-9]*$
验证非负整数(正整数 + 0)  ^\d+$
验证非正整数(负整数 + 0)  ^((-\d+)|(0+))$
验证长度为3的字符:^.{3}$
验证由26个英文字母组成的字符串:^[A-Za-z]+$
验证由26个大写英文字母组成的字符串:^[A-Z]+$
验证由26个小写英文字母组成的字符串:^[a-z]+$
验证由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
验证由数字、26个英文字母或者下划线组成的字符串:^\w+$

验证用户密码: ^[a-zA-Z]\w{5,17}$ 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线。
验证是否含有 ^%&',;=?$\" 等字符:[^%&',;=?$\x22]+
验证汉字:^[\u4e00-\u9fa5],{0,}$
验证Email地址:^\w+[-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
验证InternetURL:^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ ;^[a-zA-z]+://(w+(-w+)*)(.(w+(-w+)*))*(?S*)?$
验证电话号码:^(\d3,4|\d{3,4}-)?\d{7,8}$:--正确格式为:XXXX-XXXXXXX,XXXX-XXXXXXXX,XXX-XXXXXXX,XXX-XXXXXXXX,XXXXXXX,XXXXXXXX。
验证身份证号(15位或18位数字):^\d{15}|\d{}18$
验证一年的12个月:^(0?[1-9]|1[0-2])$ 正确格式为:“01”-“09”和“1”“12”
验证一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$    正确格式为:01、09和1、31。
整数:^-?\d+$
非负浮点数(正浮点数 + 0):^\d+(\.\d+)?$
正浮点数:  ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
非正浮点数(负浮点数 + 0): ^((-\d+(\.\d+)?)|(0+(\.0+)?))$
负浮点数:  ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:   ^(-?\d+)(\.\d+)?$

30.日期格式化-高级版

        // 获取当前时间
        let crtTime = new Date();
        console.log(crtTime);    // Mon Jun 14 2021 20:16:37 GMT+0800 (中国标准时间)
        /*
            y  年  M  月  d  日
            h  时  m  分  s  秒
        */

        // 调用函数
        let res1 = dateFormart("yyyy-MM-dd hh:mm:ss", crtTime);
        let res2 = dateFormart("yy-MM-dd hh:mm:ss", crtTime);
        let res3 = dateFormart("yyyy-M-dd hh:mm:ss", crtTime);
        let res4 = dateFormart("yyyy-MM-dd ", crtTime);
        let res5 = dateFormart("hh:mm:ss", crtTime);

        console.log(res1);      // 2021-06-14 20:16:37
        console.log(res2);      // 21-06-14 20:16:37
        console.log(res3);      // 2021-6-14 20:16:37
        console.log(res4);      // 2021-06-14
        console.log(res5);      // 20:16:37

        // 定义日期格式化函数
        function dateFormart(fmt, date) {
            // 1.处理年份
            // 1.1 通过正则表达式提取fmt字符串中的yyyy
            let yearStr = fmt.match(/y+/);

            if(yearStr){
                yearStr = yearStr[0];
                // console.log(yearStr);

                // 1.2 获取当前时间的年份
                // let yearNum = date.getFullYear();
                // 如果fmt字符串是 yyyy,yyy,yy,y 四种情况
                let yearNum = date.getFullYear() + "";
                // 则使用substr方法:从4-yearStr.length开始截取
                yearNum = yearNum.substr(4-yearStr.length);   // 2021

                // 1.3 将yyyy替换为当前时间的年份,并赋值给fmt字符串
                fmt = fmt.replace(yearStr, yearNum);
                // console.log(fmt);
            }

            // 2.处理其他时间(月 日 时 分 秒)
            // 2.1 定义对象
            // key:正则表达式(可以通过该正则表达式,获取fmt字符串中的 MM dd hh mm ss)
            // value:当前时间的 月 日 时 分 秒
            let obj = {
                "M+": date.getMonth() + 1,
                "d+": date.getDate(),
                "h+": date.getHours(),
                "m+": date.getMinutes(),
                "s+": date.getSeconds()
            };
            // 2.2 遍历对象
            for(let key in obj){
                // 1. 通过构造函数,创建正则表达式对象
                let reg = new RegExp(`${key}`);
                // console.log(reg);
                // 2. 提取fmt字符串中的 MM dd hh mm ss
                let fmtStr = fmt.match(reg);
                // console.log(fmtStr);
                if(fmtStr){
                    fmtStr = fmtStr[0];
                    // 3. 将 MM dd hh mm ss 替换为 当前时间的 月 日 时 分 秒
                    // 3.1 如果fmt字符串是一位:比如 M
                    if(fmtStr.length === 1){
                        fmt = fmt.replace(fmtStr,obj[key]);
                    }
                    // 3.2 如果fmt字符串是两位:比如 MM
                    else{
                        // 给获取到的当前月份前面添加00
                        let numStr = "00" + obj[key];
                        // "00" + 4 = "004"
                        // "00" + 12 = "0012"
                        let strNum = obj[key] + "";
                        // 不管当前月份是4月(一位数)还是12月(两位数)都从strNum.length开始截取
                        numStr = numStr.substr(strNum.length);
                        fmt = fmt.replace(fmtStr, numStr);
                    }
                }
            }
            return fmt;
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值