js的事件

本文介绍了事件的基本概念,包括事件模型、事件对象、事件流等内容,并详细讲解了内联模型、脚本模型、DOM2级模型的使用方法。此外,还探讨了如何在不同浏览器环境下实现事件绑定与解除绑定,确保代码的兼容性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事件入门

什么是事件

事件是由用户和浏览器进行交互的操作

三种事件模型内联模型

内联事件模型

作为html标签的一个属性存在的,但是这种模型已经不适合在大的项目中使用。onclick

脚本模型

但是注意的是:如果这段脚本是对整个DOM进行操作的话,必须是在DOM加载完才执行这个脚本,让事件处理函数(onclick)执行一个函数的时候,通过赋值的方式,直接将函数名赋值给事件处理函数即可,而不是为这个事件处理函数赋值为函数() 如果有括号的话会自己调用,而不是等待事件来触发

DOM2级模型

事件处理函数

onclick等事件
onkeydown 事件 按下键盘上的任意的按钮都可以输出111

    onkeydown=function(){
        console.log(111);
    }

onkeypress 事件 按下键盘上的字母键或者是数字键才可以触发这个事件,按下shift ctrl键都没有用

 onkeypress=function(){
        console.log(111);
    }

onkeyup 事件在按下键盘并释放键盘的时候才会触发这个事件

   onkeyup=function(){
        console.log(111);
    }

onunload 事件 在页面真个卸载的时候,才触发 比如说刷新的时候
onselect 事件 选择文本输入框的内容 释放的时候会触发这个事件

cc.onselect=function(){
        console.log(11);
    }

onchange 事件 文本框内改变内容并且失去焦点的时候触发
form上边的事件 这些表单必须在一个form里边
submit没有form是提交不了的,而且不是在input上边触发的,而是在form上边触发的
onresize事件 window 的事件 改变窗口的大小会触发的事件
onscroll事件 window 的事件 滚动窗体的时候会触发的事件

事件对象

事件处理的三个部分

1、DOM 2、事件处理函数 3、事件处理方法

事件对象

当触发一个事件的时候就会产生一个事件对象 浏览器通过函数把这个对象作为参数传递过来,event,所以这个对象会存在非常多的兼容性(就连得到这个对象的方式)

window.onload=function(){
    var box=document.getElementById("box");
    box.onclick=function(){
        console.log(arguments.length)    //点击的时候会传递一个事件对象  所以这里会输出1 
    }
}

所以下面的代码也可以

 var box=document.getElementById("box");
    box.onclick=function(e){
        console.log(e)    //得到的就是事件对象
    }

值得注意的是,IE中都不支持这种方式来得到事件对象,上面的方式是W3C获取事件对象的方式,在IE下可以通过window的属性直接来获取
下面的代码实现了获取事件对象的兼容

box.onclick=function(e){
        var event=window.event||e;
        alert(event)    //得到的就是事件对象
    }

鼠标事件对象跨浏览器来获得用户按下是左键?中键?右键?

window.onload=function() {
    var box = document.getElementById("box");
    document.onmouseup=function(e){
        var event=e||window.event;
        alert(getButton(e));
    }
}
function getButton(event){
    if(event){
      return event.button;
    }
    else if(window.event){
        switch(window.event.button){
            case 1: return 0;
            case 4: return 1;
            case 2: return 2;
        }
    }
}

跨浏览器获得鼠标点击位置在视窗的位置(不管你是放大了浏览器还是有了滚动条,都是看的是鼠标的点击的位置离视窗的位置),而且这个程序还可以输出有滚动条的时候,滚动条的离顶部的位置

 document.onmouseup=function(e){
        var event=window.event||e;
        alert(document.documentElement.scrollTop||document.body.scrollTop+"px"+event.clientX+"px"+ event.clientY+"px");
    }

值得注意的是:获得滚动条离最顶部的距离的时候的兼容的情况
下面这个程序是获得了鼠标点击的位置离屏幕的距离

 document.onmouseup=function(e){
        var event=window.event||e;
        alert(event.screenX+"px"+"   "+event.screenY+"px");
    }

注意:只能为alert传递一个参数
下面的函数判断是否按下修改键(shift、ctrl、alt)

window.onload=function() {
    document.onclick=function(e){
        alert(getKey(e));
    }
}
function getKey(evt) {
    var e = evt || window.event;
    var keys = [];
    if (e.shiftKey) keys.push('shift'); //给数组添加元素
    if (e.ctrlKey) keys.push('ctrl');
    if (e.altKey) keys.push('alt');
    return keys;
}

注意:上面的功能实现的是在按住shift键、ctrl键、alt键的情况下,点击屏幕会输出按下的修改键

键盘事件

keydown 按下键盘
keyup 键盘起来的时候
keypress 按下字母键盘的时候
按下键盘并返回键码keycode (键码可以返回任意键的编码,而且字母不区分大小写)

document.onkeydown=function(e){
        var event=e||window.event;
        alert(event.keyCode)
    }

但是使用了onkeypress来返回键码,在火狐浏览器中不支持(按下键盘的时候返回的是0),在谷歌浏览器和IE中虽然支持但是区分大小写

document.onkeypress=function(e){
        var event=e||window.event;
        alert(event.keyCode)
    }

火狐和谷歌浏览器都支持的事件对象都支持charCode,和keyPress搭配来得到字符编码,注意IE的事件对象没有这个属性

 document.onkeypress=function(e){
        var event=e||window.event;
        alert(event.charCode)
    }

跨浏览器获得按下键盘的编码

window.onload=function() {
    document.onkeypress=function(e){
        alert(getCharCode(e))
    }
}
function getCharCode(e){
    var event=e||window.event;
    if(typeof event.charCode=="number"){
        return event.charCode;
    }
    else{
        return event.keyCode;
    }
}

w3c和IE的事件

得到事件的目标

,(鼠标点在哪里,就可以得到哪里的dom对象)
跨浏览器获得事件的目标

window.onload=function() {
    document.onclick=function(e){
        alert(getTarget(e).tagName);
    }
}
function getTarget(e){
    var event=e||window.event;
    if(event.target){
        return event.target;
    }
    else{
        return event.srcElement
    }
}

事件流

事件流有两种模式:冒泡和捕获
这里写图片描述
html代码

<div style="background: red;width: 100px;height: 100px" id="box">
    <button > 点击</button>
</div>

js代码


window.onload=function() {
    document.onclick=function(){
        alert("documnet");
    }
    document.documentElement.onclick=function(){
        alert("html");
    }
    document.body.onclick=function(){
        alert("body");
    }
    document.getElementById("box").onclick=function(){
        alert("box");
    }
    document.getElementsByTagName("button")[0].onclick=function(){
        alert("input");
    }

}

在任何的浏览器点击按钮的时候依次会输出 input box body html document
取消冒泡模式

 document.getElementsByTagName("button")[0].onclick=function(e){
        alert("input");
        e.stopPropagation();  //IE不支持
    }

只是取消了点击按钮的冒泡
跨浏览器阻止事件冒泡

function stopBubble(e){
    var event=e||window.event;
    (typeof event.stopPropagation=="function")? event.stopPropagation(): event.cancelBubble=true;
}

事件绑定

传统事件绑定

如果一个页面有两个或者多个js脚本文件,导致会有多个window.onload这两个事件,这就会导致第一个window.onload会被覆盖,解决的方法:在使用window.onload的时候,首先要检测是否存在window.onload是否是一个函数
下面就是解决覆盖的问题

window.onload=function () {
     alert("dd");
}
if(typeof window.onload=="function"){
    var saved=null;
    saved=window.onload;
}window.onload=function () {
    if(saved)saved();
    alert("cc");
}

事件切换器

<style>
    .red{
        background: red;
        width:200px;
        height: 200px;
    }
    .blue{
        background: blue;
        width:200px;
        height: 200px;
    }
</style>
<body>
  <div id="test" class="blue"></div>
</body>

js代码

window.onload=function () {
    var test=document.getElementById("test");
    console.log(test)
    test.onclick=toBlue;
}
function toRed(){
    this.className='red';
    this.onclick=toBlue;
}
function toBlue(){
    this.className='blue';
    this.onclick=toRed;
}

注意,通过匿名函数执行一个函数,那么这个函数里面的this就会代表window,但是匿名函数这个this中还是属于当前对象的

  test.onclick=function(){
        alert(this);   //div
        toBlue();
    };
    function toBlue(){
    alert(this);   //会弹出window
    this.className='blue';
    this.onclick=toRed;
}

所以下面的这个代码也实现了事件的切换

 test.onclick=function(){
        toBlue.call(this);
    };
    function toRed(){
    this.className='red';
    this.onclick=toBlue;
}
function toBlue(){
    this.className='blue';
    this.onclick=toRed;
}

所以传统事件的绑定有许多的缺点,所以我们要自定义函数来实现事件的绑定
有一点值得注意window.onload相当于window[“onload”]

//obj  相当于window
//type   相当于onload
//fn    相当于function
function addEvent(obj,type,fn){
    removeEvent(obj,type);   //一道切的移除事件的函数
    var saved=null;
    if(typeof obj['on'+type]=='function'){
        saved=obj['on'+type];
    }
    obj['on'+type]=function(){
        if(saved){
            saved();
        }
        //用它来做事件切换器   注意this
        fn.call(this);
    }
}
function removeEvent(obj,type){
    if(typeof obj['on'+type]=='function') {
        obj['on'+type]=null;
    }
}

使用新的绑定事件的方式实现事件切换器

addEvent(window,'load',function () {
    var test=document.getElementById("test");
    addEvent(test,'click',toBlue)
})
function toRed(){
    this.className='red';
    addEvent(this,'click',toBlue);
}
function toBlue(){
    this.className='blue';
    addEvent(this,'click',toRed);
}

W3C事件绑定机制

DOM2级定义了两个事件的处理方法 添加事件 删除事件
也就是addEventListener()和removeEventListener()但是这两个方法只能在支持W3C的事件模型的浏览器上运行
传递的参数 对象.addEventListener('事件',事件处理函数,捕获(true)还是冒泡false)

window.addEventListener('load',function () {
    alert(11);
},false)
window.addEventListener('load',function () {
    alert(22);
},false)

1、DM2级事件模型的绑定事件解决了覆盖的问题(一次会弹出11 22)

window.addEventListener('load',init,false)
window.addEventListener('load',init,false)
window.addEventListener('load',init,false)
function init() {
    alert(1);
}

2、相同的函数多次绑定到同一个函数的时候,会自动的屏蔽(会之弹出一次1,自动屏蔽)

window.addEventListener('load',function () {
    var test=document.getElementById("test");
    test.addEventListener('click',toBlue,false);
},false)
function toRed() {
    this.className="red";
    this.removeEventListener('click',toRed,false);   //必须要有这一步,否则没有办法进行事件的切换
    this.addEventListener('click',toBlue,false);
}
function toBlue() {
    this.className="blue";
    this.removeEventListener('click',toBlue,false); //必须要有这一步,否则没有办法进行事件的切换
    this.addEventListener('click',toRed,false);
}

3、可以传递this,实现事件的切换器,直接在toRed使用this

    test.addEventListener('click',function () {
        alert(11);
    },false);
    test.addEventListener('click',toBlue,false);

4、添加一个额外的方法,会不会被覆盖或者只执行了一次,实现了点击的时候既可以弹出11也可以变色
综上所述,W3C的addEventListener和removeEventListener完美的解决了事件的绑定,但是IE8及其以下的版本都不支持DOM2级的这个事件模型,而是采用了自己的事件。
冒泡和捕获(设置true和false)

   test.addEventListener('click',function () {
        alert("div");
    },true);
    document.addEventListener('click',function () {
        alert("document")
    },true);

设置为了捕获,点击div的时候,先弹出document再弹出div

IE事件处理函数

注意以下的测试必须在IE8及以下完成:
attachEvent(‘on+事件名称’,’事件处理函数’)
detachEvent(‘事件名称’,’事件处理函数’)
因为IE8以下中的事件
1、不支持捕获,
2、IE事件不能屏蔽重复的函数
3、IE中的this指向的是widow而不是DOM对象(不可以传递this)
4、传统的IE事件模型上,IE是无法接收到event对象,但是使用了attachEvent()却可以
但是也解决了
1、覆盖问题

window.attachEvent('onload',function () {
    alert(1);
})
window.attachEvent('onload',function () {
    alert(2);
})

但是会先弹出2 在弹出1
让IE和W3C兼容这个事件切换器
1、跨浏览器添加事件

function addEvent(obj,type,fn) {
    if(obj.addEventListener){
        obj.addEventListener(type,fn,false);
    }else if(obj.attachEvent){
        obj.attachEvent('on'+type,fn)
    }
}

2、夸浏览器移除事件

function removeEvent(obj,type,fn) {
    if(obj.removeEventListener){
        obj.removeEventListener(type,fn);
    }else if(obj.detachEvent){
        obj.detachEvent('on'+type,fn)
    }
}

3、跨浏览器获取目标对象

function getTarget(e) {
    if(e.target){
        return e.target;
    }
    else if(window.event.srcElement){
        return window.event.srcElement
    }
}

事件对象的其他补充

W3C的relatedTarget这个属性可以在mouseover和mouseout事件中获取从哪里移入和从哪里移出

  <span id="pox">
      <div id="box"></div>
  </span>

js代码

addEvent(window,'load',function () {
      var box=document.getElementById("box");
    addEvent(box,'mouseover',function (evt) {
         alert(evt.relatedTarget)  //得到移入box的最近的对象   会弹出span
    })
})

跨浏览器阻止事件的默认行为

//跨浏览器阻止事件的默认行为
function predefault(evt) {
    var event=evt||window.event;
    if(event.preventDefault)
    {
        event.preventDefault();
    }
    else{
        event.returnValue=false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值