JavaScript精粹(六)- 事件

在 JavaScript 中,事件处理是网页交互的核心。事件是用户与页面交互时发生的行为,比如点击、滚动、鼠标移动等操作。JavaScript 提供了一套完整的事件模型,包括事件对象、事件监听、事件委托等功能,用于实现页面交互和响应用户行为。

  1. 事件对象:
    • 当事件发生时,会自动生成一个事件对象(Event Object),该对象包含了与事件相关的信息,比如事件类型、触发元素、鼠标位置等。
    • 开发者可以通过事件对象来获取这些信息,并根据其执行相应的操作。
  2. 监听事件:
    • 监听事件是指为 HTML 元素绑定一个或多个事件处理函数,当事件触发时,该函数会被调用。
    • 常见的事件包括 click、mousedown、mouseup、mousemove、keydown、keyup 等等。
    • 监听事件的方法有多种,最常用的是 addEventListener() 和 attachEvent() 方法。
  3. 事件委托:
    • 事件委托是一种将事件处理从子元素传递到父元素的技术,可以提高性能和代码可维护性。
    • 委托的原理是利用事件冒泡机制,在父元素上监听事件,然后根据事件目标元素的不同执行不同的操作。
    • 通过事件委托,可以减少事件处理器的数量,避免重复绑定事件,同时也能够应对动态添加或删除元素的情况。


二十一、event事件

1.1 event 事件对象

当事件触发的时候产生的对象,存储着和事件相关的信息
chrome、firefox、IE9+等:事件函数的第一个形参就是事件对象

document.onclick = function(e){
    alert( e );
};

chrome、IE8以下:全局变量 event

document.onclick = function(){
    alert( event );
};

兼容

document.onclick = function(ev){
    ev = ev || window.event;
};

那么,在event事件对象里面有哪些信息呢?我们一起来看一下

1.2 相对于窗口的位置

  • ev.clientX 存储鼠标相对于窗口的水平坐标
  • ev.clientY 存储鼠标相对于窗口的垂直坐标

1.3 相对于文档的位置

  • ev.pageX 存储鼠标相对于文档的水平坐标(不兼容IE8及以下)
  • ev.pageY 存储鼠标相对于文档的垂直坐标(不兼容IE8及以下)

IE8以及以下

ev.clientY + document.documentElement.scrollTop || ev.pageY

1.4 ev.button

  • 0------按下左键
  • 1------按下滚轮键
  • 2------按下右键
document.onmousedown = function (ev) {
        ev = ev || window.event;
        alert(ev.button)
    }

1.5 oncontextmenu

返回false表示屏蔽右键菜单

    document.oncontextmenu = function () {
        return false;
}

那么,有什么用呢?我们可以结合鼠标按键先屏蔽掉默认的右键菜单然后自己去定义

1.6 onselectstart

文本不能被选中

    document.onselectstart = function () {
         return false;
    }

也可以

<html lang="en" onselectstart="return false">

我们之前也讲过一个css3的属性

user-select: none;

1.7 ev.keyCode键值:

1.7.1 键盘事件

按下

document.onkeydown = function () {
}

一直按 同时存在的时候down 优先于press

document.onkeypress = function () {
}

键盘抬起

document.onkeyup = function () {
}

1.7.2 ev.keyCode键值

键盘上每个键都对应着一个数值

document.onkeydown = function (ev) {
        ev = ev || window.event;
        console.log(ev.keyCode);
 }

1.8 表单事件

1.8.1 checked

在js里面,单选或者复选框里面的checked属性会被强制转换为布尔值
我们默认的不给checked写实际上就是给了checked="checked"

var oInput = document.getElementById('input');
console.log(oInput.checked);  //true

等价

oInput.checked = "checked";
console.log(oInput.checked);   //true

给的值会被强制转换为Boolean值,因此我们直接写布尔值效率要高很多

oInput.checked = false;       //如果我们给他false就表示不选中

1.8.2 获取失去焦点

获取焦点

    inp.onfocus = function () {
        console.log('获取焦点');
    }

也可以用函数直接运行,当页面刷新的时候就处于获取焦点的状态

obj.focus()

失去焦点

    inp.onblur = function () {
        console.log('失去焦点');
    }

也可以用函数直接运行,当页面刷新的时候就处于获取焦点的状态

obj.blur();

1.8.3 onchange

当表单内容发生改变的时候触发

  • text 当内容改变的时候失去焦点触发
  • radio 选中变成非选中触发
  • checkbox 选中变成非选中触发
  • select 选中内容改变的时候

1.8.4操作下拉列表

<select name="" id="">
    <option value="1">111</option>
    <option value="2">222</option>
    <option value="3">333</option>
</select>
sel.onchange = function () {
        var value = this.options[this.selectedIndex].text; //获取option标签里面的内容
        console.log(value);  
        console.log(this.value);  //获取value里面的值
    }

其中:

  • this.selectedIndex 是对应的option标签的索引值
  • .text也可以表示为.innerHTML表示获取里面的内容

1.9 滚轮事件

1.9.1 滚轮事件兼容

谷歌和IE浏览器

document.onmousewheel = function(){
        console.log(1);
};

火狐浏览器

document.addEventListener('DOMMouseScroll',function () {
    console.log(1);
});

兼容:

function mousewheel(obj , eFn) {
   document.onmousewheel===null?obj.onmousewheel=eFn:obj.addEventListener('DOMMouseScroll',eFn);
}

当谷歌和IE的时候是支持onmousewheel的,但是这个时候没有绑定事件函数那么值就是null空对象,这个时候我们再将eFn赋值给他,当不支持onmousewheel的时候为undefined则添加addEventListener

1.9.2 e.wheelDelta

在chrome和IE里,12 或者 3的倍数,负值代表向下滚轮(贴近胸),正值代表向上滚轮(往上推)

console.log(e.wheelDelta);

在firefox里,3的倍数,负值代表向上滚轮(往上推),正值代表向下滚轮(贴近胸)

console.log(e.detail);

兼容:
判断delta的正负就可以知道向上滚轮还是向下滚轮(向前正,向后负)

var delta = e.wheelDelta/12 || -e.detail/3;

除以他们的倍数是为了可以明确的知道滚了多少次了

1.10 ev.cancelBubble冒泡

    <div class="box1">
        <div class="box2">
            <div class="box3"></div>
        </div>
    </div>
 
    oBox1.onclick = daGOu;
    oBox2.onclick = daGOu;
    oBox3.onclick = daGOu;
    function daGOu() {
        alert(this.className);
    }

当执行的时候我们会发现,点击box2的时候会执行box2的事件也会执行box1的事件,点击box3的时候,会执行box1,box2,box3的事件,我们可以看出,就好像从内到外冒泡一样的,那么我们怎么去解决呢?

阻止冒泡

   ev.cancelBubble = true        浏览器都可以但是不符合W3C标准 (是一个属性)
   ev.stopPropagation()     适用于chrome fireFox 不支持IE 符合W3C标准 (是一个方法)
oBox1.onclick = daGOu;
    oBox2.onclick = daGOu;
    oBox3.onclick = daGOu;
    function daGOu(ev) {
        ev = ev || window.event;
        ev.cancelBubble = true;
        alert(this.className);
    }

二十二、添加事件监听

1.1 添加事件

1.1.1 传统添加事件

在网站的开发和维护中,给一个对象绑定事件以后我们不方便再去改变他,那么如果我们还要想给他添加新事件的时候,如果我们用以前的添加事件的方式去添加

oBox.onclick = function(){
alert( 1 );
};
oBox.onclick = function(){
alert( 2 );
};

这样子后面添加的事件会把前面的覆盖掉
为了避免不覆盖原来的,我们就要用到新的注册事件的方式。

1.1.2 添加事件监听

  1. 主流浏览器写法(去掉on的事件名 , 事件函数,布尔值【可以不写】 默认false)
oBox.addEventListener('click' , function(){
    alert('1');
} , false);
oBox.addEventListener('click' , function(){
    alert('2');
} , false);
  1. IE8及以下写法
oBox.attachEvent( 'onclick' , function(){
    alert( 1 );
} );
oBox.attachEvent( 'onclick' , function(){
    alert( 2 );
} );
  1. 兼容写法
document.addEventListener?obj.addEventListener(eName,eFn):obj.attachEvent('on'+eName , eFn);
};
 
addEvent( oBox,'click' , function(){
    alert( 1 );
} );
addEvent( oBox,'click' , function(){
    alert( 2 );
} );

1.2 解绑事件

1.2.1传统事件的解绑

oBox.onclick = function(){
alert(1);
};
oBox.onclick = null;

1.2.2 监听事件解绑

oBox.addEventListener('click' , function(){
alert('1');
} , false);
oBox.removeEventListener('click' , function(){
alert('1');
});

但是,我们可以发现这样子是解绑不了的,因为函数是引用类型,不仅比较值,还要比较内存地址不相等的。

所以,我们只能这样子

IE8以上:

oBox.addEventListener('click' , fn2);
oBox.removeEventListener('click' , fn2);
function fn2(){
alert('2');
};

也就是三个对应:

  • 事件名对应
  • 事件函数要对应
  • 布尔值要对应

IE8以下:

oBox.detachEvent('onclick' , fn2);

1.2.3 添加和解绑事件兼容:

function addEvent(obj,eName,eFn) {
    if(obj.arr){
        obj.arr.push(eFn); //数组里面有值以后就把后面添加的函数push进去就行了
    }else{
        obj.arr = [eFn]; //自定义一个属性,将函数存进去
    }
    obj.addEventListener ? obj.addEventListener(eName,eFn) : obj.attachEvent('on'+eName,eFn);
}
function removeEvent(obj,eName,eFn) {
    if(eFn){
        for( var i=0; i<obj.arr.length; i++ ){
            if(obj.arr[i] + '' === eFn + ''){//将存起来的函数都和remove里面的函数换成字符串进行比较,如果相等,就解绑这一个函数
                obj.removeEventListener ? obj.removeEventListener(eName,obj.arr[i]) : obj.detachEvent('on'+eName,obj.arr[i])
            }
        }
    }else{
        for( var i=0; i<obj.arr.length; i++ ){
            obj.removeEventListener ? obj.removeEventListener(eName,obj.arr[i]) : obj.detachEvent('on'+eName,obj.arr[i]);
        }
    }
}

二十三、事件委托

1.1 小案例

我们先做一个小案例,在box大盒子中有几个小盒子,点击的时候会变成粉红色。当点击添加按钮的时候,会在后面添加新的盒子,并且点击添加的小盒子也能变成粉红色

怎么样去实现这个功能呢?

第一步:需要给里面所有小盒子添加点击事件

for( var i=0; i<aP.length; i++ ){
        aP[i].addEventListener('click',function () {
            this.style.background = 'deeppink';
        })
    }

第二步:当点击按钮的时候,增加小盒子,也就是我们要创建节点,但是小盒子的点击事件在之前就添加了的,后面添加的小盒子并没有被注册点击事件,这时候就需要我们在注册一遍点击事件。

oBtn.onclick = function () {
        var p = document.createElement('p');  //在dom中创建节点
        p.innerHTML = ++n;
        p.addEventListener('click',function () {
            this.style.background = 'deeppink';
        });
        oBox.appendChild(p);  //将创建的节点添加到box盒子里面
    }

1.2 认识事件委托

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

oBox.addEventListener('click',function (e) {
        e = e || window.event;
        console.log(e.currentTarget); //添加监听的那个对象(当前对象)
        console.log(e.target); //点击的对象(目标对象)
    })

1.3用事件委托解决小案例

oBox.addEventListener('click',function (e) {
       e = e || window.event;
       if(e.target.tagName === 'P')e.target.style.background = 'deeppink';
   });
    oBtn.addEventListener('click',function () {
        var p = document.createElement('p');
        p.innerHTML = ++n;
        oBox.appendChild(p);
    })

【上一篇】JavaScript精粹(五)- DOM&BOM&offset
【下一篇】JavaScript精粹(七)- 正则表达式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

经理,天台风好大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值