BOM基础

321 阅读9分钟

笔记来源:拉勾教育 - 大前端就业集训营

文章内容:学习过程中的笔记、感悟、和经验

BOM

BOM和Window对象

BOM

浏览器对象模型,提供独立于内容的,可与浏览器窗口进行交互的对象结构,

BOM有多个对象组成,其中window代表浏览器窗口对象,为BOM的顶层对象,其他对象都是window的子对象(document就是)

我们在浏览器中的一些操作可以使用BOM的方式进行编程处理,比如:刷新、后退、前进、输入url等

Window对象

特点:window对象下面的属性和方法大部分不需要添加window前缀就可以直接调用

  • 我们定义在全局的变量都相当于给window添加了一个属性
  • 我们平常使用的alert等其他方法实际使用的是window内部的方法,使用window.alert同样可以调用实现
  • window下的两个特殊属性,我们尽量不要创建全局同名变量:
    • window.name:这是window本身存在的属性,我们尽量不要在全局作用于中创建name变量,如果创建赋值结果会被强制转换为字符串类型
    • window.top:这条属性指顶层对象window,这个属性是只读的,我们不能覆盖和修改。

对话框

三种对话框弹出方法

  • alert():弹出提示
  • prompt():弹出用户输入 --- 返回字符串类型文本
  • confirm():弹出确定取消 --- 返回布尔类型值

我们在日常工作中,一般不会使用这三种,因为这三种会阻塞js代码,影响后续代码的运行,真正工作中我们一般使用其他方法模拟弹出框来制作

<body>
    <input id="button1" type="button" value="alert">
    <input id="button2" type="button" value="prompt">
    <input id="button3" type="button" value="condirm">
    <script>
        //获取元素
        var button1 = document.getElementById('button1'),
            button2 = document.getElementById('button2'),
            button3 = document.getElementById('button3');
        //添加点击事件
        button1.onclick = function () {
            window.alert('hello');
        }
        button2.onclick = function () {
            console.log(window.prompt('请输入'));
            //返回用户输入内容的字符串
        }
        button3.onclick = function () {
            console.log(window.confirm('你确定?'));
            //返回布尔值,点击确定返回true,取消返回flase
        }
    </script>
</body>

加载事件-onload

我们可以给window对象或者任意一个元素添加onload加载事件,表示绑定事件的元素加载完毕后才能触发事件,才能执行事件函数

其中window的加载事件,表示需要所有HTML结构、引入的外部资源(js、css、音视频)全部加载完毕后才会执行事件函数

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box {
            width: 200px;
            border: 10px solid red;
        }

        #box img {
            display: block;
            width: 200px;
        }
    </style>
</head>

<body>
    <div id="box">
        <img src="./images/lunbo/01.jpg" alt="">
        <img src="./images/lunbo/02.jpg" alt="">
        <img src="./images/lunbo/03.jpg" alt="">
        <img src="./images/lunbo/04.jpg" alt="">
        <img src="./images/lunbo/05.jpg" alt="">
    </div>
    <script>
        // 问题: 我们想知道box标签的高度,但不能直接获取,根据谷歌浏览器熏染机制,如果碰到img标签,那么浏览器会为了避免标签等待时间过长,先执行后面的js代码,这样后面如果直接获取box高度会显示为0

        // 获取我们要知道高度的box标签
        var box = document.getElementById('box'),
            // 获取box下面的所有img标签
            imgs = box.getElementsByTagName('img');

        // 利用计数器计算执行了多少个img标签,当发现全部img都执行完毕后,输出box高度
        // 计数器
        // var num = 0;
        // 循环遍历img标签
        // for (let i = 0; i < imgs.length; i++) {
        //依次执行每个img的onload事件
        //     imgs[i].onload = function () {
        // 让计数器自增
        //         num++;
        //当发现计数大于等于img长度之后,代表全部渲染完成,然后就可以输出box高度了
        //         if (num >= imgs.length) {
        //             console.log(box.clientHeight);
        //         }
        //     }
        // }


        //我们使用window.onload方法更简单粗暴,但是由于window的onload只有在整个页面全部加载完成后才能执行,所以等待时机那会比较长
        window.onload = function () {
            console.log(box.clientHeight);
        }
    </script>
</body>

</html>

应用

利用window的onload事件,可以把js代码放在HTML结构之前,把js代码写在onload事件内部

一个页面只能有一个window。onload事件,如果多个下面的会覆盖上面的

延时器

创建

在指定的事件之后,执行某段特定代码,是window对象的方法

语法:window.setTimeout(延时函数,时间);

  • 参数1:延时执行的函数,可以是匿名函数,也可以是函数调用,不要加()
  • 参数2:延时时间,没有单位的整数,代表多少毫秒,即1000===1000毫秒===1秒

清除

也是window的一个方法,用来清除指定的延时器

语法:window.clearTimeout(变量名)

参数:指定的延时器变量名引用

需要清除的延时器必须预先存储在一个变量中,便于后期清除调用

// 延时器,把延时器赋值给一个变量,依旧可以执行
var me = window.setTimeout(boom, 3000);
// 延时器后面执行
console.log('我在延时器后面,但我先执行了');
// 延时执行函数
function boom() {
    console.log('我炸了');
}
// 解除延时器me
window.clearTimeout(me);
// 再输出一条语句看看
console.log('别等了,炸弹被我拆了');

函数节流(防骚扰)

为了防止用户短期内频繁操作或者频繁访问,我们需要对操作频率进行一些控制

<body>
    <button id="btn">点我</button>
    <script>
        // 需求:点击按钮输出随机数,但我们为了防止频繁访问,每两秒才能输出一次

        //获取元素
        var btn = document.getElementById('btn');
        //创建一个锁,true代表锁住(不可以执行操作),flase代表打开(可以执行操作)
        var me = false;
        // 给元素添加click事件
        btn.onclick = to;
        //事件函数
        function to() {
            // 判断锁是否打开
            if (me) {
                //如果是关闭的,直接返回
                return;
            }
            // 如果打开输出随机数
            console.log(Math.random());
            // 把锁锁上,让用户不能执行操作
            me = true;
            // 两秒后再把锁打开
            setTimeout(function () {
                me = false;
            }, 2000)
        }
    </script>
</body>

定时器

创建

每隔一个指定时间,执行特定函数,重复执行。是window的一个方法,自动执行

语法:window.setInterval(函数,时间)

  • 参数1:每次执行的函数,匿名函数或者引用都可以,不加()
  • 参数2:时间间隔,和延时器一样,一个没有单位的整数,1000===1000毫秒===1秒

定时器不会立马执行,需要有一次时间间隔才会执行第一次

清除

也是window的一个方法,用来清除指定的定时器

语法:window.clearInterval(变量名)

参数:指定的定时器变量名引用

需要清除的定时器必须预先存储在一个变量中,便于后期清除调用

// 创建一个定时器,每隔两秒输出执行一次
var me = setInterval(function () {
    console.log('我来了');
    console.log('我走了');
}, 2000);
// clearTimeout(me);  //使用清除延时器方法也能清除定时器
//清除定时器方法
clearInterval(me);

简单运动

一种视觉暂留效果,只要元素变化过程足够短,人眼就会觉得这是一个连续的运动,人眼视觉暂留时间0.1-0.4秒之间;

制作方法:通过定时器,实现每隔一个极短的时间(50-100毫秒),执行函数,函数内部让运动的属性发生变化

<body>
    <!-- 运动盒子 -->
    <div id="box"></div>
    <script>
        //获取元素
        var box = document.getElementById('box');
        //创建一个方向参数,true向右运动,flase向左运动
        var to = true;
        //(信号值)创建一个left,代表定位的left数值,我们通过修改这个值控制运动
        var left = 0;
        // 创建一个定时器,每隔两秒输出执行一次
        var time = setInterval(function () {
            //修改css的left值,从而修改box位置
            box.style.left = left + 'px';
            // 判断运动方向
            if (to) {
                //如果方向向右,left每次增加10
                left += 10;
                //判断left是否超过200,如果超过让方向变反
                if (left >= 200) {
                    to = false
                }
            } else {
                //如果方向向左,每一步减掉10
                left -= 10;
                //判断left是否到达0,如果到达0,反转方向
                if (left <= 0) {
                    to = true;
                }
            }
            //每50毫秒执行一次
        }, 50)
    </script>
</body>

提高速度的方法

  • 缩短时间,增加每秒步进次数
  • 加大步长,让每一次长度增加

定时器清除问题

多次点击问题

将定时器和清除器放在不同事件函数内部,容易造成用户错误点击的情况

  • 多次点击开始:会造成加速(相当于创建了多个定时器,速度逐渐累加)
  • 多次点击开始,无法停止(每次点击创建一个定时器,停止只能停止最新的定时器)
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        div {
            position: fixed;
            top: 100px;
            width: 30px;
            height: 30px;
            background: pink;
        }
    </style>
</head>

<body>
    <!-- 开始按钮 -->
    <button id="btn">开始</button>
    <!-- 停止按钮 -->
    <button id="endbtn">停止</button>
    <!-- 运动盒子 -->
    <div id="box"></div>
    <script>
        //获取元素
        var box = document.getElementById('box');
        var btn = document.getElementById('btn');
        var endbtn = document.getElementById('endbtn');
        //(信号值)创建一个left,代表定位的left数值,我们通过修改这个值控制运动
        var left = 0;
        // 创建一个定时器变量
        var time;
        // 开始按钮开始事件
        btn.onclick = function () {
            //创建定时器赋值变量
            time = setInterval(function () {
                //修改css的left值,从而修改box位置
                box.style.left = left + 'px';
                //left每次增加10
                left += 10;
                // 每50毫秒执行1次函数
            }, 50)
        }
        // 停止按钮事件,
        endbtn.onclick = function () {
            // 停止定时器
            clearInterval(time);
        }


        //如果点击多次开始按钮,会产生多个定时器,每个定时器的速度会相加,造成加速效果
        //因为点击了多次,但是每次点击都会重新定义time变量的指向,time变量只会指向最新的定时器
        //点击time的时候只会停止最新的定时器,其他定时器不会停止,就导致停不下来
        //停止了最新的定时器,可以看出来速度慢了一点下来
    </script>
</body>

</html>

解决方案--设表先关(执行前先清除)

在执行定时器之前先清除定时器,这样就不会造成多个定时器同时存在的问题

// 代码使用上面的

// 设表先关:每次开启定时器之前都要清除一次定时器
btn.onclick = function () {
            // 清除之前的定时器
            clearInterval(time);
            //创建定时器赋值变量
            time = setInterval(function () {
                //修改css的left值,从而修改box位置
                box.style.left = left + 'px';
                //left每次增加10
                left += 10;
                // 每50毫秒执行1次函数
            }, 50)
        }

拉终停表问题(停在指定位置)

在定时器内部每次都要判断是否走到了终点,如果到了或者超过了终点强行把位置拉到终点,并停止定时器(不用担心下面代码会停止,只是停止下一次循环)

btn.onclick = function () {
    // 清除之前的定时器
    clearInterval(time);
    //创建定时器赋值变量
    time = setInterval(function () {
      
        //拉终停表
        // 判断是否超过500
        if (left >= 500) {
            // 如果大于等于500,强制把信号值拉到500
            left = 500;
            //停止定时器
            clearInterval(time);
        }
      
        //修改css的left值,从而修改box位置
        box.style.left = left + 'px';
        //left每次增加10
        left += 35;
        // 每50毫秒执行1次函数
    }, 50)
}

步标整除

需求:在规定时间内,让元素从开始位置走到结束为止,时间间隔可更改

例如:让元素在2秒内,从0走到500

原理

我们已知初始位置、结束位置、总时间、每次时间间隔,那么我们就可以求出每次运动的步长

步长=(终止位置-起始位置)/ (总时间 / 时间间隔)

此方法可放方便我们日后对代码进行更改,如果我们要更改步长、起始位置、开始位置、间隔时长都可以,程序会自动帮我们进行运算

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        div {
            position: fixed;
            top: 100px;
            width: 30px;
            height: 30px;
            background: pink;
        }
    </style>
</head>

<body>
    <!-- 开始按钮 -->
    <button id="btn">开始</button>
    <!-- 停止按钮 -->
    <button id="endbtn">停止</button>
    <!-- 运动盒子 -->
    <div id="box"></div>
    <script>
        //获取元素
        var box = document.getElementById('box'),
            btn = document.getElementById('btn'),
            endbtn = document.getElementById('endbtn'),
            // 创建一个定时器变量
            time,
            //(起始位置--信号值)创建一个left,代表定位的left数值,我们通过修改这个值控制运动
            nowLeft = 0,
            // 结束为止
            endLeft = 500,
            // 总时间 2000毫秒
            zsj = 2000,
            // 时间间隔 50毫秒
            sjjg = 50,
            // 总次数(总时长/时间间隔)
            zcs = zsj / sjjg,
            // 计算步长(终止位置-起始位置)/(总时长/时间间隔)
            speed = (endLeft - nowLeft) / zcs,
            // 累加器,用来判断定时器进行了多次,如果超过大于等于总次数(总次数可能是小数)则停止
            num = 0;
        // 开始按钮开始事件
        btn.onclick = function () {
            // 清除之前的定时器,避免发生多次点击开始加速的问题
            clearInterval(time);
            //创建定时器赋值给变量
            time = setInterval(function () {
                //left每次增加一个步长
                nowLeft += speed;
                //先让定时器自增
                num++;
                //判断定时器是否大于等于总次数
                if (num >= zcs) {
                    // 条件成立,拉终停表
                    nowLeft = endLeft;
                    // 删除定时器
                    clearInterval(time);
                }
                //修改css的left值,从而修改box位置
                box.style.left = nowLeft + 'px';
            }, sjjg)
        }
        // 停止按钮事件,
        endbtn.onclick = function () {
            // 停止定时器
            clearInterval(time);
        }
    </script>
</body>

</html>

封装动画函数

如果多个属性值发生改变,需要更改的变量太多

获得元素计算后属性window.getComputedStyle(元素),可以获取元素渲染计算后的元素的CSS属性值

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        div {
            position: fixed;
            top: 100px;
            width: 100px;
            height: 100px;
            background: pink;
            opacity: 0.5;
        }
    </style>
</head>

<body>
    <!-- 开始按钮 -->
    <button id="btn">开始</button>
    <!-- 停止按钮 -->
    <button id="endbtn">停止</button>
    <!-- 运动盒子 -->
    <div id="box"></div>

    <script>
        // 获取元素
        var box = document.getElementById('box');
        // 封装动画函数,实现多属性动画效果
        // 参数1:ele--动画元素
        // 参数2:end--一个封装所有变化属性的对象,属性值为最终值
        // 参数3:time--动画总时长
        function animate(ele, end, time) {
            //我们默认动画时间间隔为50ms
            //计算最大次数 (总时长/间隔时间)
            var maxcount = time / 50;
            // 创建一个容纳当前属性的对象nowStyle,接下来获取的当前属性都存储在这里
            var nowStyle = {};
            // 新建一个容纳每种属性步长的对象,我们把计算后的步长都存放在这里
            var speed = {};
            // 累加器,用来计数定时器次数,一旦超过最大次数我们要求删除定时器
            var num = 0;

            // 遍历end获取每个属性的属性名
            for (var k in end) {
                // 获取每个属性值的现有计算属性,并把属性和属性值添加到nowStyle中
                // window.getComputedStyle可以获取全部计算好的属性
                nowStyle[k] = parseFloat(getComputedStyle(box)[k]);
            }

            // 遍历end对象,获得属性值
            for (var k in end) {
                // 计算步长,步长 =(最终值-初始值)/最大次数,把步长和对应的属性值添加到speed中
                speed[k] = (end[k] - nowStyle[k]) / maxcount;
            }

            // 创建一个计时器
            var timer = setInterval(function () {
                // 根据步长计算新的nowStyle,(初始值+步长)
                for (var k in end) {
                    nowStyle[k] += speed[k];
                }
                // 累加器累加
                num++;
                // 判断累加器是否大于等于最大次数
                if (num >= maxcount) {
                    //如果到了再大次数,拉终停表,把每一个nowStyle拉到最大值
                    for (var k in end) {
                        nowStyle[k] = end[k];
                    }
                    // 停止定时器
                    clearInterval(timer)
                }
                // 把nowStyle值添加给元素的行内属性
                for (var k in nowStyle) {
                    // 如果发现属性值是opacity,添加的行内样式不要加px
                    if (k === 'opacity') {
                        box.style[k] = nowStyle[k];
                    } else {
                        // 给元素添加css行内样式
                        box.style[k] = nowStyle[k] + 'px';
                    }
                }
                // 每50ms执行一次
            }, 50);
        }

        // 调用函数
        animate(box, {
            left: 500,
            width: 200,
            height: 200,
            opacity: 1
        }, 2000);
    </script>
</body>

</html>

案例:简单无风滚动轮播图

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .scroll {
            position: relative;
            width: 830px;
            height: 130px;
            border: 10px solid #000;
            margin: 100px auto;
            overflow: hidden;
        }

        .scroll ul {
            position: absolute;
            top: 0;
            left: 0;
            width: 5000px;
            height: 130px;
        }

        .scroll ul li {
            float: left;
            width: 200px;
            height: 130px;
            margin-right: 10px;
            overflow: hidden;
        }
    </style>
</head>

<body>
    <div class="scroll" id="scroll">
        <ul id="munit">
            <li><img src="images/shuzi/0.png" alt="" /></li>
            <li><img src="images/shuzi/1.png" alt="" /></li>
            <li><img src="images/shuzi/3.png" alt="" /></li>
            <li><img src="images/shuzi/4.png" alt="" /></li>
            <li><img src="images/shuzi/5.png" alt="" /></li>
            <li><img src="images/shuzi/6.png" alt="" /></li>
            <li><img src="images/shuzi/7.png" alt="" /></li>
            <li><img src="images/shuzi/0.png" alt="" /></li>
            <li><img src="images/shuzi/1.png" alt="" /></li>
            <li><img src="images/shuzi/3.png" alt="" /></li>
            <li><img src="images/shuzi/4.png" alt="" /></li>
            <li><img src="images/shuzi/5.png" alt="" /></li>
            <li><img src="images/shuzi/6.png" alt="" /></li>
            <li><img src="images/shuzi/7.png" alt="" /></li>
        </ul>
    </div>
    <script>
        // 获取元素
        var munit = document.getElementById('munit');
        var scroll = document.getElementById('scroll');
        // 获取现有的left值
        var now = parseFloat(window.getComputedStyle(munit).left);
        // 创建默认执行定时器
        var timer = setInterval(run, 50);
        // 鼠标移上删除定时器
        scroll.onmouseover = function (e) {
            clearInterval(timer);
        }
        // 鼠标移开新建定时器
        scroll.onmouseout = function (e) {
            timer = setInterval(run, 50);
        }

        // 定时器运动函数
        function run() {
            now -= 20;
            if (now + 1470 <= 0) {
                now = 0;
            }
            munit.style.left = now + 'px';
        }
    </script>
</body>

</html>

案例:高级无缝滚动轮播图

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .scroll {
            position: relative;
            width: 830px;
            height: 130px;
            border: 10px solid #000;
            margin: 100px auto;
            overflow: hidden;
        }

        .scroll .inner {
            position: relative;
            width: 5000px;
        }

        .scroll ul {
            position: absolute;
            top: 0;
            left: 0;
            height: 130px;
            list-style: none;
        }

        .scroll ul li {
            float: left;
            margin-right: 10px;
        }
    </style>
</head>

<body>
    <div class="scroll" id="scroll">
        <div class="inner">
            <ul id="munit">
                <li><img src="images/shuzi/0.png" alt="" /></li>
                <li><img src="images/shuzi/1.png" alt="" /></li>
                <li><img src="images/shuzi/2.png" alt="" /></li>
                <li><img src="images/shuzi/3.png" alt="" /></li>
                <li><img src="images/shuzi/4.png" alt="" /></li>
                <li><img src="images/shuzi/5.png" alt="" /></li>
                <li><img src="images/shuzi/6.png" alt="" /></li>
            </ul>
        </div>
    </div>
    <!-- 如果加上这句话就不需写在window.onload里面了,原因是js程序是单线程的,当加载到这里的时候会先去加载common.js,但是加载图片是异步的,等到common.js加载完后图片也加载完了,这时候就已经可以直接读取宽度了
但是,如果图片很多,可能会导致js加载完图片还没渲染完,这样就会导致宽度依旧不准,所以还是建议尽量把代码写在window.onload里面-->
    <!-- <script src="common.js"></script> -->
    <script>
        // 为了避免浏览器加载图片的问题,我把代码写在window.onload里面
        window.onload = function () {
            // 获取元素
            var scroll = document.getElementById('scroll');
            var munit = document.getElementById('munit');
            // 获取最大的位移距离
            var back = munit.offsetWidth;
            // 使li数量翻倍
            munit.innerHTML += munit.innerHTML;
            // 创建初始位移量(信号值)
            var nowLeft = 0;

            // 创建定时器
            var timer = setInterval(run, 10);

            // 鼠标移上盒子删除定时器
            scroll.onmouseover = function () {
                clearInterval(timer);
            }

            // 鼠标移开创建定时器
            scroll.onmouseout = function () {
                timer = setInterval(run, 10);
            }

            // 定时器函数
            function run() {
                nowLeft -= 5;
                if (nowLeft + back <= 0) {
                    nowLeft = 0;
                }
                munit.style.left = nowLeft + 'px';
            }
        }
    </script>
</body>

</html>

案例:完整切换效果轮播图

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

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

        ul,
        ol {
            list-style: none;
        }

        .carousel {
            position: relative;
            width: 880px;
            height: 550px;
            border: 1px solid #333;
            margin: 50px auto;
        }

        .pic li {
            position: absolute;
            left: 0;
            top: 0;
            width: 880px;
            height: 550px;
            display: none;
        }

        .pic li.current {
            display: block;
        }

        .btn a {
            position: absolute;
            top: 50%;
            width: 80px;
            height: 80px;
            margin-top: -40px;
            background-color: rgba(255, 255, 255, 0.3);
            text-decoration: none;
            color: #444;
            text-align: center;
            line-height: 80px;
            font-size: 60px;
            font-family: "SimSun";
        }

        .btn .left {
            left: 10px;
        }

        .btn .right {
            right: 10px;
        }

        .btn a:hover {
            background-color: rgba(255, 255, 255, 0.7);
        }

        .sub {
            position: absolute;
            bottom: 30px;
            left: 50%;
            width: 200px;
            height: 40px;
            margin-left: -100px;
            border-radius: 20px;
            background-color: rgba(255, 255, 255, 0.3);
        }

        .sub li {
            float: left;
            width: 20px;
            height: 20px;
            margin: 10px;
            border-radius: 50%;
            background-color: #ccc;
            cursor: pointer;
        }

        .sub li.current {
            background-color: #0ff;
        }
    </style>
</head>

<body>
    <div class="carousel" id="carousel">
        <ul class="pic" id="pic">
            <li class="current"><img src="images/lunbo/01.jpg" alt=""></li>
            <li><img src="images/lunbo/02.jpg" alt=""></li>
            <li><img src="images/lunbo/03.jpg" alt=""></li>
            <li><img src="images/lunbo/04.jpg" alt=""></li>
            <li><img src="images/lunbo/05.jpg" alt=""></li>
        </ul>
        <div class="btn" id="btn">
            <a href="javascript:;" class="left" id="leftbtn">&lt;</a>
            <a href="javascript:;" class="right" id="rightbtn">&gt;</a>
        </div>
        <ol class="sub" id="sub">
            <li class="current"></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ol>
    </div>
    <script>
        // 需求:
        // 1、点击右按钮可以切换下一张图片
        // 2、点击左按钮可以切换上一张图片
        // 3、点击下方小圆点可以切换到对应图片
        // 4、图片会每隔两秒自动切换下一张
        // 5、鼠标移上停止对自动循环播放
        // 6、鼠标移开继续循环播放

        // 思路:
        // 我们使用特殊类名current来实现切换效果,所以我们只需要修改我们想要的图片和小圆点的类名即可实现切换效果,我们可以使用一个信号量来作为中间值,每次我们只需要修改信号量即可实现切换效果


        // 获取元素
        // 整体大盒子
        var carousel = document.getElementById('carousel'),
            //ul标签
            pic = document.getElementById('pic'),
            //底部小原点ol标签
            sub = document.getElementById('sub'),
            //获取图片li标签数组和底部小圆点数组
            imgs = pic.children,
            subs = sub.children,
            //左右两个按钮元素
            leftbtn = document.getElementById('leftbtn'),
            rightbtn = document.getElementById('rightbtn'),
            //建立一个信号量,后续的全部操作都要基于这个信号量
            nowImg = 0;
        //创建一个默认的计时器,每两秒执行一次,直接执行点击右侧按钮操作,因为自动切换和点击右侧按钮的效果是一样的
        var zdqh = setInterval(toright, 2000);
        // 右侧按钮点击事件
        rightbtn.onclick = function () {
            //这里重置一下计时器
            //先删除自动切换计时器
            clearInterval(zdqh);
            //调用toright函数执行切换下一张
            toright();
            //重新建立一个计时器,开始自动循环播放
            zdqh = setInterval(toright, 2000);
        }
        // 左侧按钮点击事件
        leftbtn.onclick = function () {
            // 原理同上,重置计时器,调用toLeft函数实现切换上一张
            clearInterval(zdqh);
            toLeft();
            zdqh = setInterval(toright, 2000);
        }
        // 给底部每一个按钮添加点击事件,
        for (let i = 0; i < subs.length; i++) {
            //点击事件
            subs[i].onclick = function () {
                //修改信号量
                nowImg = i;
                //重置定时器,调用xrtp函数渲染切换图片
                clearInterval(zdqh);
                xrtp();
                zdqh = setInterval(toright, 2000);
            }
        }
        //  鼠标移上删除定时器
        carousel.onmouseover = function () {
            clearInterval(zdqh);
        }
        //鼠标移开重建定时器
        carousel.onmouseout = function () {
            zdqh = setInterval(toright, 2000);
        }


        //功能:修改信号量,每次调用+1,到达最大值设为0
        function toright() {
            if (nowImg < imgs.length - 1) {
                nowImg++
            } else {
                nowImg = 0;
            }
            // 调用xrtp渲染切换图片
            xrtp();
        }
        //功能:修改信号量,每次调用-1,到达最小值设为最大值
        function toLeft() {
            if (nowImg > 0) {
                nowImg--;
            } else {
                nowImg = imgs.length - 1;
            }
            // 调用xrtp渲染切换图片
            xrtp();
        }
        //功能:渲染图片,使用排他思想
        function xrtp() {
            // 重置图片和底部小圆点类名
            for (let i = 0; i < imgs.length; i++) {
                imgs[i].className = '';
                subs[i].className = '';
            }
            //修改需要的图片和小圆点类名
            imgs[nowImg].className = 'current';
            subs[nowImg].className = 'current';
        }
    </script>
</body>

</html>

案例:返回顶部

补充:谷歌浏览器中,不能使用document.body.scrollTop获取滚动值,可以使用document.documentElement.scrollTop获取

//获取元素
var wrap = my$('wrap'),
  wrapTop = my$('top'),
  toTop = my$('totop'),
  content = my$('content');
//给全局window一个监测滚动的事件
window.onscroll = function () {
  //获取滚动距离
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop
  //判断滚动距离,如果滚动距离大于10,修改顶部类型,让返回顶部按钮出现
  if (scrollTop > 10) {
    wrapTop.className = 'header fixed';
    toTop.style.display = 'block'
  } else {
    wrapTop.className = 'header';
    toTop.style.display = ''
  }
}
//返回顶部按钮点击事件
toTop.onclick = function () {
  //新建信号值,获取现在的滚动距离
  var now = document.documentElement.scrollTop;
  //获取步长,我们指定让他在250ms内完成滚动
  var speed = document.documentElement.scrollTop / 5;
  //新建计时器
  var timer = setInterval(function () {
    //信号值
    now -= speed;
    //判断信号值是否小于等于0
    if (now <= 0) {
      //如果到达了顶点,拉终停表
      now = 0;
      clearInterval(timer);
    }
    //修改滚动值
    document.documentElement.scrollTop = now;
    //每50ms滚动一次
  }, 50);
}

location对象

是window的一个属性,使用时可以不写window

可以获取或者设置浏览器的地址栏的URL

可以直接console.log(location)查看内部属性和方法

常用属性和方法

属性和方法说明
href当前url地址,可以赋值修改
assign(新地址)类似href,调用可获取或者修改url,保留历史(可返回)
replace(新地址)替换url,替换页面url,不保留历史,不可返回
reload(true、flase)刷新页面,true表示从服务器刷新,flase优先从本地缓存获取数据

URL了解

统一资源定位符(Uniform Resource Locator, URL)

URL的组成: scheme ://host spor t/path?quer y#fr agment

例如: http://www. lagou. com: 80/ a/ b/ index. html ?name=zs&age=1 8#bottom

  • scheme:通信协议,常用的http, ftp, ma ito等
  • host:主机,服务器(计算机)域名系统(DNS) 主机名或IP地址。
  • port:端口号,整数,可选,省略时使用方案的默认端口,如http的默认端口为80。
  • path:路径,由零或多个'/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
  • query:查询,可选,用于给动态网页传递参数,可有多个参数,用'&' 符号隔开,每个参数的名和值用'='符号隔开。例如: name=zs
  • fragment:信息片断,字符串,锚点

里面的各个属性日后可以在location里面对应找到,日后遇到时在进行查找即可

history对象

也是window的一个属性,是一个对象,使用时可以忽略window

可以与浏览器的历史记录进行交互

常用方法

  • back():返回历史记录中上一个页面
  • forward():前进到历史记录中下一个页面(前提是历史记录中有一个页面)
  • go(n):前进或者后退,参数为正值,标签前进n个页面,负值表示回退n个页面

日常工作中一般不使用,一般使用浏览器自带的即可