JS(三)之不同浏览器下的事件

事件对象

案例 — div跟随鼠标移动

案例初期
  1. HTML
<body style="height: 1000px;">
	<div id= "box1"></div>
</body>
  1. CSS
#box1{
	width : 100px;
	height : 100px;
	background-color : red;
	position : absolute;
}
  1. Script
document.onload = function(){
	var box = document.getElementById("box1");
	document.onmousemove = function(event){
		event = event || window.event;
		var left = event.clientX;
		var top = event.clientY;
	
		box.style.left = left + "px";
		box.style.top = top + "px";
	}
}
  • event = event || window.event
    IE8中,响应函数被触发时,浏览器不会传递事件对象
    在IE8及以下的浏览器中,是将事件对象作为window对象的属性来保存的
  • clientXclientY用于获取鼠标在当前的窗口的坐标

以上代码在div小于浏览器窗口的时候,才适用。然而div的偏移量应该是相对于整个页面的

  • pageXpageY可以获取鼠标相对于当前页面的坐标
    然而IE8不支持
案例修正版
  • 实际滚动轴的距离+鼠标在页面当前窗口的坐标 = div的实际坐标

  • 获取滚动条滚动的距离 document.body.scrollTop

    • chrome认为浏览器的滚动条是body的,可以通过body.scrollTop来获取
    • 火狐等浏览器认为浏览器的滚动条是HTML的
    • HTML的滚动高度使用documentElement.scrollTop
  • Script修改最终版

document.onload = function(){
	var box = document.getElementById("box1");
	document.onmousemove = function(event){
		event = event || window.event;
		
		var left = event.clientX;
		var top = event.clientY;
		var st = document.body.scrollTop || document.documentElement.scrollTop;
		var sl = document.body.scrollLeft || document.documentElement.scrollLeft;
		
	
		box.style.left = left + st + "px";
		box.style.top = top + sl + "px";
	}
}

事件的冒泡Bubble

  • 所谓的冒泡指的就是事件的向上传导,当后代元素上的时间被触发时,其祖先元素的相同事件也会被触发
  • 在开发中大部分冒泡是有用的,如果不希望事件冒泡可以通过事件对象来取消冒泡event.cancleBubble = true;,以下举例无用冒泡
    1.HTML
<div id="box1">
        我是box1
        <span id="s1">
            我是span
        </span>
    </div>
  1. JS
document.onload = function(){
            var s1 = document.getElementById("s1");
            s1.onclick = function (event) {
                alert("我是span的单击函数");

                event = event || window.event;
                event.cancelBubble = true;
            }
            var box1 = document.getElementById("box1");
            box1.onclick = function (event) {
                alert("我是div的单击函数");

                event = event || window.event;
                event.cancelBubble = true;
            }
            document.body.onclick = function (event) {
                alert("我是body的单击函数");

                event = event || window.event;
                event.cancelBubble = true;
            }
        }

事件的委派

  1. html
<button id="btn01">添加超链接</button>
<ul id="ul">
    <li><a href="javascript:;">超链接1</a></li>
    <li><a href="javascript:;">超链接2</a></li>
    <li><a href="javascript:;">超链接3</a></li>
</ul>

2.JS 为每一个链接绑定事件,并设置按钮,添加链接

document.onload = function(){
            var allA = document.getElementById("a");
            for (var i = 0; i <allA.length; i++) {
                allA[i].onclick = function () {
                    alert("我是a的单击相应函数");
                }
            }
            var btn = document.getElementById("btn01");
            btn.onclick = function () {
                var li = document.createElement("li");
                li.innerHTML ="<a href='javascript:;'>新建超链接</a>";
                allA.append(li);
            }
        }

新增的链接是不会触发点击事件的,必须重新绑定,因此我们希望绑定一次,应用到多个元素上,即使元素是后添加的。尝试将其绑定给元素的共同的祖先元素

ul.onclick = function(){
	alert("我是ul的单击相应函数");
}
  • 这就是事件的委派
    • 指将事件统一绑定给元素的共同的族元素,这样当后代元素上的时间触发,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件
    • 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
  • 如果在a链接需要制定特定的元素执行,可以使用event.target获取对象进行特定的判定

事件的绑定

onclick只能存在一个,最后一个覆盖前者。
  • 如果需要触发事件的时候,执行多个处理函数
    • IE8及以上浏览器,使用addEventListener
      • 第一个参数:事件不用on
      • 第二个参数,回调函数
      • 输出this,返回的是绑定时间的对象
      • 先绑定的先执行
    • 在IE8以下可以使用attachEvent
      • 第一个参数:事件用on
      • 第二个参数,回调函数
      • 输出this,返回的是window
      • 后绑定的后执行
  • 然而在IE8以上的浏览器不认为attachEvent是一个方法
  • 定义一个函数,用来为指定元素绑定相应函数
function bind(obj, eventStr, callBack){
	if(obj,addEventListener){
		//大部分浏览器兼容你的方式
		obj,addEventListener(eventStr, callBack, false);
	}else{
		//IE8及以下
		obj.attachEvent("on"+eventStr, callBack);
	}
}
  • 参数:
    obj 要绑定的对象
    eventStr 事件的字符串
    callback 回调函数
  • 存在的问题:this不同,说明callBack内,不好使用this
    • callBack不是由我们调用的,否则可以使用 callBack.call(obj);指定this
    • 解决方法:在匿名函数中,调用callBack.call(obj);
事件绑定修正版bind
function bind(obj, eventStr, callBack){
	if(obj,addEventListener){
		//大部分浏览器兼容你的方式
		obj,addEventListener(eventStr, callBack, false);
	}else{
		//IE8及以下
		obj.attachEvent("on"+eventStr, function (){
			callBack.call(obj);
		});
	}
}

事件的传播

  • 关于时间的传播网景公司和微软公司有不同的理解
  • 微软公司认为事件应该是由内向外传播,也就是当时间触发,应该先触发当前元素上的事件,然后再向当前元素上的祖先元素上传播,也就说时间应该在冒泡阶段执行。
  • 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后在向内传播给后代元素
  • W3C综合了俩个公司的方案,将事件传播分为了三个阶段
    1. 捕获阶段
      • 在补货阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默许此时不会触发事件
    2. 目标阶段
      • 事件捕获到目标元素,捕获借书可以在目标元素上触发事件
    3. 冒泡阶段
      • 事件从目标元素向他的祖先事件传递,依次触发祖先元素上的事件
  • 如果希望在不胡阶段剧触发事件,可以将addEventListener()的第三个参数设置为true,一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
  • IE8及以下的浏览器中没有捕获阶段
  • 图解在这里插入图片描述

案例二 — 鼠标拖拽div

  1. CSS
#box1{
            width:100px;
            height: 100px;
            position: absolute;
            background-color: yellow;
        }
  1. HTML
<p>ninghao</p>
<div id="box1"></div>
  1. JS
window.onload = function () {
            var box1 = document.getElementById("box1");
            box1.onmousedown = function (event) {
                event = window.event || event;
                var sl = event.clientX - box1.offsetLeft;
                var st = event.clientY - box1.offsetTop;

           
                box1.setCapture && box1.setCapture();
                document.onmousemove = function (event) {
                    event = window.event || event;
                    
                    var left = event.clientX - sl;
                    var top = event.clientY - st;
                    box1.style.left = left+"px";
                    box1.style.top = top+"px";
                }
                document.onmouseup = function () {
                    document.onmousemove = null;
                    document.onmouseup = null;
                    box1.releaseCapture && box1.releaseCapture();
                }
                return false;
            }
       }

4.代码说明
- 移动前的div与移动后的div 的偏移距离,可以使div跟随鼠标移动,而不会点击非左上角的时候,div的左上角坐标等于点击div的坐标,产生卡顿效果。
在这里插入图片描述

  • 当我们拖拽一个网页的内容时,浏览器会默认去搜索引擎中搜索内容
    • 此时会导致拖拽功能的异常,这个是浏览器的默认行为
    • 如果不希望发生这个行为,可以通过 return false来取消默认行为
    • 但是这招对IE8不适用,解决方案:
    • setCapture()releaseCapture鼠标捕获
      • 但是setCapture 只有IE支持,但是在火狐调用时不会报错
      • 而如果使用chrome调用时,会报错
    • box1.releaseCapture&& box1.releaseCapture();

鼠标滚动事件

  • onmousewheel鼠标滚动事件,会在滚轮滚动的时候触发
    • 但是火狐不支持该属性
    • 在火狐中需要使用DOMMouseScroll来绑定滚动事件
      • 注意:该事件需要通过addEventListener()函数来绑定
      • 举例:
  • HTML
<div id= "box1"></div>
  • CSS
#box1{
	width :100px; 
	height:100px;
	position:absolute;
}
  • JS
var box1 = document.getElementById("box1");

box1.onmousewheel = function (event){
	event = event || window.event;
	
	//判断滚轮方向
	if(event.wheelDelta > 0 || event.detail < 0){
	    //向上
	    box1.style.height = box1.clientHeight - 10 +"px";
	}else{
		//向下
		 box1.style.height = box1.clientHeight + 10 +"px";
	}
};
event.peventDefault();
return false;
bind(box1,"DOMMousScroll",box1.onmousewheel );
  1. event.wheelDelta这个属性火狐不支持
    • 原因: event.detail火狐使用此属性来获取滚动的方向
    • 结论:if(event.wheelDelta > 0 || event.detail < 0)判断方向
  2. 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,如果不希望发生,则可以取消默认行为。return false火狐不能
    • 原因:火狐在使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false,event来取消默认行为event.preventDefault
    • 结论:event.peventDefault();return false;同时使用,然而IE8不支持event.preventDefault()
    • 最终结论:使用event.preventDefault && event.preventDefault()

键盘事件

  • 键盘事件一般会给可以获取到焦点的对象或者是document
  • 键盘事件:
    • onkeydown
      • 按键被按下
      • 对于onkeydown来说如果一直按着某个按键不松手,则事件一直会被触发
      • 连续操作在第一次操作的时候都会卡一点,这是浏览器为了防止误操作(定时器可以修改)
    • onkeyup
      -event.keyCode altKey ctrlKey shiftKey这个可以任意组合判断
  • 例如:输入框的onkeydownreturn false,可以阻止输入框默认行为,但是文本框输入内容为keydown的默认行为
    • 这样,可以限制输入框内容只能输入数字
  • onkeydown连续操作控制div移动
    1.HTML
    <div id="box"></div>
  1. CSS
#box{
            height:100px;
            width: 100px;
            background-color: yellow;
            position: absolute;
        }
  1. JS
window.onload = function(){
            var box = document.getElementById("box");
            document.onkeydown = function (event) {
                event = event || window.event;
                var speed = 10;
                if(event.ctrlKey){
                    speed = 500;
                }
                switch (event.keyCode) {
                    case 37:
                        box.style.left = box.offsetLeft - speed +"px";
                        break;
                    case 38:
                        box.style.top = box.offsetTop - speed +"px";
                        break;
                    case 39:
                        box.style.left = box.offsetLeft + speed +"px";
                        break;
                    case 40:
                        box.style.top = box.offsetTop + speed +"px";
                        break;
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值