JavaScript入门到精通(十二)



本章节通过练习需要重点掌握对滚轮事件、键盘事件的操作并反复练习切换图片

110. 事件的传播

网景公司和微软公司对事件的传播有着不同的理解:
网景公司:认为事件应该是由外向内传播,即当事件触发时应该先触发当前元素的最外层的祖先元素的事件,然后再向内传播给后代元素
微软公司:认为事件应该是由内向外传播,即当事件触发时应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就是事件应该在冒泡阶段执行

W3C综合了两者的方案,将事件传播分成了三个阶段:
   1.捕获阶段:从最外层的组选元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
   2.目标阶段:事件捕获到目标元素,开始触发事件
   3.冒泡阶段:事件从目标元素向祖先元素传播,依次触发祖先元素上的事件

如果希望在捕获阶段触发事件,可以将addEventListener( )的第三个参数设置为true。一般情况下不会希望在捕获阶段触发事件,因此该参数一般为false

在IE8及以下的浏览器没有捕获阶段

在这里插入图片描述

<!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>
        #box1{
            width: 300px;
            height: 300px;
            background-color: aqua;
        }
        #box2{
            width: 200px;
            height: 200px;
            background-color: blue;
        }
        #box3{
            width: 100px;
            height: 100px;
            background-color: blueviolet;
        }
    </style>
    <script>
        window.onload = function(){
            var box1 = document.getElementById("box1");
            var box2 = document.getElementById("box2");
            var box3 = document.getElementById("box3");

            bind(box1,"click",function(){
                alert("我是box1的响应函数");
            });
            bind(box2,"click",function(){
                alert("我是box2的响应函数");
            });
            bind(box3,"click",function(){
                alert("我是box3的响应函数");
            });
        };

        function bind(obj,eventStr,callback){
            if(obj.addEventListener){
                //大部分浏览器兼容的方式
                obj.addEventListener(eventStr,callback,true);
            }else{
                //IE8以及下
                obj.attachEvent("on"+eventStr,function(){
                    callback.call(obj);//在匿名函数中调用回调函数,改变this
                });
            }
        }
    </script>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
</body>
</html>

可以看到,当改为true后,先触发box1的响应函数,再触发box2、box3

在这里插入图片描述

111. 拖拽

练习:拖拽div元素

拖拽的流程:
1.当鼠标在被拖拽元素上按下时,开始拖拽
2.当鼠标移动时,被拖拽元素跟随鼠标移动
3.当鼠标松开时,被拖拽元素固定在当前位置

当我们拖拽一个网页中内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能的异常,如果不希望发生这个行为,可以通过return false来取消默认行为,但不支持IE8

对于IE8可以通过设置捕获所有事件来解决,但setCapture( )方法在chrome浏览器会报错

因此要解决兼容问题

<!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>
        #box1{
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
        #box2{
            width: 100px;
            height: 100px;
            background-color: orange;
            position: absolute;
            left: 200px;
            top: 200px;
        }
    </style>
    <script>
        window.onload = function(){
            var box1 = document.getElementById("box1");
            var box2 = document.getElementById("box2");
            drag(box1);
            drag(box2);
            var img = document.getElementById("img");
            drag(img);
        };
        function drag(obj){
            obj.onmousedown = function(e){//为box1绑定鼠标按下事件
                if(obj.setCapture){
                    obj.setCapture();//设置box1捕获所有鼠标按下事件
                }
                // box1.setCapture && box1.setCapture();
                e = e || window.e;
                //求出div的偏移量
                var ol = e.clientX - obj.offsetLeft;
                var ot = e.clientY - obj.offsetTop;

                document.onmousemove = function(e){//为document绑定鼠标移动事件
                    e = e || window.e;//解决兼容性问题
                    var x = e.clientX - ol;
                    var y = e.clientY - ot;
                    obj.style.left = x + "px";
                    obj.style.top = y + "px";
                };
                document.onmouseup = function(){//为document绑定鼠标松开事件
                    document.onclick = null;//设置为空,即为取消该事件响应函数
                    document.onmousemove = null;
                    if(obj.releaseCapture){
                        obj.releaseCapture();
                    }
                    // box1.releaseCapture && box1.releaseCapture();
                };
                return false;
            };
        }
    </script>
</head>
<body>
    <div id="box1"></div>
    <div id="box2"></div>
    <span>今天天气不错</span>
    <img src="../img/1.gif" style="position: absolute;" id="img">
</body>
</html>

在这里插入图片描述

112. 滚轮的事件

练习:当鼠标滚轮向下滚动时,box变长;向上滚动时,box变短

onmousewheel:鼠标滚轮滚动事件,但火狐中不支持
DOMMouseScroll:为火狐绑定鼠标滚轮滚动事件,要使用addEventListener( )绑定响应函数

event.wheelDelta:可以获取鼠标滚轮滚动方向,不看大小只看正负,但火狐不支持
向上滚:120
向下滚:-120

event.detal:火狐中获取鼠标滚轮滚动方向,不看大小只看正负
向上滚:-3
向下滚:3

当滚轮滚动时,如果浏览器有滚动条,则浏览器滚动条会跟着滚动
可以通过return false取消这个默认值,但火狐中不支持

火狐是使用addEventListener( )绑定响应函数的,取消默认行为不能使用return false,需要使用event.preventDefault( ),但该方法不支持IE8

因此要解决兼容性问题

<!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>
        #box1{
            width: 100px;
            height: 100px;
            background-color: blue;
        }
    </style>
    <script>
        window.onload = function(){
            var box1 = document.getElementById("box1");
            box1.onmousewheel = function(e){
                e = e || window.e;
                if(e.wheelDelta > 0 || e.detail < 0){//获取鼠标滚轮滚动方向,向上变短
                    box1.style.height = box1.clientHeight - 10 + "px"; 
                }else{
                    box1.style.height = box1.clientHeight + 10 + "px"; 
                }
                e.preventDefalut && e.preventDefalut();//火狐取消浏览器滚动条滚动的默认事件
                return false;//其它浏览器取消浏览器滚动条滚动的默认事件
            };
            bind(box1,"DOMMouseScroll",box1.onmousewheel);//火狐滚轮滚动事件

        };

        function bind(obj,eventStr,callback){
            if(obj.addEventListener){
                //大部分浏览器兼容的方式
                obj.addEventListener(eventStr,callback,false);
            }else{
                //IE8以及下
                obj.attachEvent("on"+eventStr,function(){
                    callback.call(obj);//在匿名函数中调用回调函数,改变this
                });
            }
        }
    </script>
</head>
<body style="height: 2000px;">
    <div id="box1"></div>
</body>
</html>

在这里插入图片描述

113. 键盘事件

onkeydown:按键被按下,如果一直按着则事件会一直触发;当连续触发时,第一次和第二次间隔会稍微长一些,其它的间隔一样,目的是为了防止误操作的发生
onkeyup:按键被松开

键盘事件一般绑定给可以获取焦点的对象或文档document对象

可以通过event.keycode获取按键的编码,从而判断那个按键被按下
altkey,ctrlkey,shiftkey这三个用来判断alt,strl,shift是否被按下,是则返回true

在文本框中输入内容属于onkeydown的默认行为,如果取消了默认行为则输入内容不会出现在文本框中

<!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>
    <script>
        window.onload = function(event){
            document.onkeydown = function(event){
                event = event || window.event;
                if(event.keyCode ===89 && event.ctrlKey){
                    alert("ctrl和y键都被按下了")
                }
            };

            var input = document.getElementsByTagName("input")[0];
            input.onkeydown = function(event){
                event = event || window.event;
                // alert(event.keyCode);
                if(event.keyCode >=48 && event.keyCode <= 57){
                    return false;//取消文本框默认行为,则输入内容不会出现在文本框中
                }
            };
        };
    </script>
</head>
<body>
    <input type="text">
</body>
</html>

在这里插入图片描述

【注意】不要使用小键盘里的数字,小键盘数字0-9的keycode为96-105

114. 键盘移动div

<!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>
        #box{
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
    </style>
    <script>
        //w:87,s:83,a:65,d:68
        window.onload = function(){
            var box = document.getElementById("box");
            document.onkeydown = function(e){
                e = e || window.e;
                var speed = 10;
                if(e.shiftKey){
                    speed = 50;
                }
                if(e.keyCode == 87){
                    box.style.top = box.offsetTop - speed + "px";
                }else if(e.keyCode == 83){
                    box.style.top = box.offsetTop + speed + "px";
                }else if(e.keyCode == 65){
                    box.style.left = box.offsetLeft - speed + "px";
                }else if(e.keyCode == 68){
                    box.style.left = box.offsetLeft + speed + "px";
                }
            };
        };
    </script>
</head>
<body>
    <div id="box"></div>
</body>
</html>

在这里插入图片描述

115. nvigator

BOM:浏览器对象模型,通过JS来操作浏览器
DOM:文档对象模型,通过JS来操作网页

BOM对象:
   Window:代表整个浏览器窗口,也是网页中的全局对象
   Navigator:代表当前浏览器的信息,可以来识别不同的浏览器
   Location:代表当前浏览器的地址栏信息,可以跳转页面
   History:代表浏览器的历史记录,由于隐私原因,该对象不能获取到具体的历史记录,只能操作向前或向后翻页,而且该操作只在当次访问时有效
   Screen:代表用户屏幕的信息,可以获取到用户的显示器的相关信息

这些BOM对象在浏览器中都是作为window对象的属性保存的,可以通过window对象来使用,也可以直接使用

Naigator代表当前浏览器的信息,由于历史原因,Navigator对象中的大部分属性都已经不能帮助我们识别浏览器了,一般只会使用userAgent来判断浏览器信息
userAgent:返回一个字符串,含有用来描述浏览器信息的内容,不同浏览器返回不同

IE中已经将微软和IE相关的标识都去除了,所以基本已经不能通过userAgent来识别IE11

如果通过userAgent不能判断,还可以通过一些特有的对象,来判断浏览器的信息
比如:ActiveXObject

<!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>
    <script>
        console.log(window);
        console.log(navigator);
        console.log(location);
        console.log(history);
        console.log(screen);

        console.log(navigator.appName);//Netscape

        console.log(navigator.userAgent);

        var ua = navigator.userAgent;
        if(/firefox/i.test(ua)){
            alert("火狐浏览器")
        }else if(/chrome/i.test(ua)){
            alert("chrome浏览器")
        }else if(/msie/i.test(ua)){
            alert("IE浏览器");
        }else if("ActiveXObject" in window){
            alert("IE11浏览器")
        }
    </script>
</head>
<body>
    
</body>
</html>

在这里插入图片描述

116. history

history对象可以操作浏览器向前或向后翻页

length属性:获取当前访问的链接数量

back( ):方法,用来回退到上一个页面,和浏览器回退按钮一样
forward( ):方法,用来跳转到下一个页面,和浏览器前进按钮一样
go( ):方法,用来跳转到指定的页面,需要一个整数作为参数
   1:表示向前跳转1个页面,相当于forward( )
   2:表示向前跳转2个页面
   -1:表示向后回退1个页面,相当于back( )
   -2:表示向后回退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>Document</title>
    <script>
        window.onload = function(){
            var btn = document.getElementById("btn");
            btn.onclick = function(){
                // history.back();
                // history.forward();
                history.go(1);
            }}</script>
</head>
<body>
    <a href="https://www.baidu.com/">访问百度</a>
    <br>
    <button id="btn">前进/回退</button>
</body>
</html>

在这里插入图片描述

117. location

如果打印location则可以获取到地址栏的信息(当前页面的完整路径)

如果直接将location属性修改为一个完整的路径或相对路径,则会自动跳转到该路径并生成相应历史记录

assign( ):方法,用来跳转到其它页面,作用和直接修改location一样
reload( ):方法,用来重新加载当前页面,作用和刷新按钮一样,如果传true作参数,则会强制清空缓存并刷新页面
replace( ):方法,用一个新页面替换当前页面,调用完毕也会跳转页面,但不会生成历史记录,即不能使用回退按钮回退页面

<!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>
    <script>
        window,onload = function(){
            var btn = document.getElementById("btn");
            btn.onclick = function(){
                console.log(location);

                // location = "https://www.baidu.com/";

                // location.assign("https://www.baidu.com/");//跳转页面,可以回退
                // location.reload(true);//强制清空缓存并刷新页面
                location.replace("https://www.baidu.com/");//跳转页面,但不能回退
            };
        
        };
    </script>
</head>
<body>
    <input type="text">
    <button id="btn">按钮</button>
</body>
</html>

在这里插入图片描述

118. 定时器简介

window方法:定时调用
如果希望一段程序可以每间隔一段时间执行一次,可以使用定时调用

setInterval( ):方法,将一个函数每间隔一段时间执行一次
参数:1.回调函数
    2.间隔时间,单位毫秒
    返回值,Number类型数据,作为定时器的唯一标识

clearInterval( ):方法,用来关闭一个定时器,
参数:定时器标识

<!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>
    <script>
        window.onload = function(){
            var count = document.getElementById("count");
            var num  = 1;
            var timer = setInterval(function(){
                count.innerHTML = num++;
                if(num == 10){
                    clearInterval(timer);
                }
            },1000);//定时调用
        };
    </script>
</head>
<body>
    <h1 id="count"></h1>
</body>
</html>

在这里插入图片描述

119. 切换图片练习

clearInterval( )可以接收任意参数,如果参数为有效的定时器标识,则会停止对于的定时器,如果参数非有效的标识,则什么也不做

目前每点击一次按钮就会开启一个定时器,这就导致图片切换速度过快,且只能关闭最后一次开启的定时器

因此在开启一个新定时器之前,需要将当前元素上的定时器关闭

<!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>
    <script>
        window.onload = function(){
            var img = document.getElementsByTagName("img")[0];
            var count = 0;
            var timer;

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

            var btn1 = document.getElementById("btn1");
            btn1.onclick = function(){
                clearInterval(timer);//开启新定时器之前,关闭上一个定时器
                timer = setInterval(function(){
                if(count > 4){
                    count = 0;
                }
                console.log(count);
                img.src = "../img/" + (count+1) + ".gif";
                p.innerText = "当前显示为第" + (count+1) + "张图片"
                count ++;
                },1000);
            };

            var btn2 = document.getElementById("btn2");
            btn2.onclick = function(){
                clearInterval(timer);
            };

            
            
        };
    </script>
</head>
<body>
    <p id="p">当前显示为第1张图片</p>
    <img src="../img/1.gif">
    <br>
    <button id="btn1">开始循环播放图片</button>
    <button id="btn2">停止循环播放图片</button>
</body>
</html>

在这里插入图片描述



下一章节将对延时调用、轮播图、类操作、二级菜单和JSON进行深入了解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值