简单理解js中的事件对象

基本概念:

1. 事件基础:在js中,事件是可以被JS侦测到的行为。

2. 事件函数:当事件被触发时,调用的函数。

//  事件函数:当事件被触发时,调用的函数。
var box = document.getElementsByName('box')[0];
box.onclick = function () {
    console.log('hello');
}
//onclick= 后面的函数部分就是事件函数。

3. 事件对象:

  • 当事件发生时,浏览器会将事件相关的信息保存到内置的全局对象window.event中,可以直接使用。

注意:有些版本的火狐不支持event属性,返回undefined,所以获取不到事件对象;我这个可能因为我的是最新版本的  你们可以自己测试一下。

document.onclick = function () {
    //  Chrome浏览器: MouseEvent {isTrusted: true, screenX: 324, screenY: 169, clientX: 324, …}
    //  IE浏览器:[object MSEventObj]{actionURL: "",  ...}
    //  火狐浏览器:click { target: html, buttons: 0, clientX: 120, clientY: 103, layerX: 120, layerY: 103 }
    console.log(event);
}
  • 标准浏览器的事件对象,当事件被触发时候,通过事件函数的第一个参数出入。
// 2. 方式二:
// 标准浏览器的事件对象,当事件被触发时候,通过事件函数的第一个参数出入
document.onclick = function (ev) {
    //  Chrome浏览器:MouseEvent {isTrusted: true, screenX: 210, screenY: 179, clientX: 210, …}
    //  IE9及其以上浏览器:[object MSEventObj]{actionURL: "",  ...}
    //  IE8及其以下  不支持  返回undefined
    //  火狐浏览器:click { target: html, buttons: 0, clientX: 220, clientY: 36, layerX: 220, layerY: 36 }
    console.log(ev);
}
  • 兼容的写法
document.onclick = function (ev) {
    ev = ev || event;
    //  Chrome浏览器:MouseEvent {isTrusted: true, screenX: 210, screenY: 179, clientX: 210, …}
    //  IE浏览器:[object MSEventObj]{actionURL: "",  ...} 
    //  火狐浏览器:click { target: html, buttons: 0, clientX: 220, clientY: 36, layerX: 220, layerY: 36 }
    console.log(ev);
}

3.1 事件对象中的属性

  1. 获取当前触发事件类型;ev.type;

  2. 获取当前触发的对象;ev.target;     在IE8及其以下写ev.srcElement来获取对象。

    •  兼容性获取: var target = ev.target || ev.srcElement;

  3. 获取当前点击的位置,相对于可视区窗口;  ev.clientX, ev.clientY

  4. 获取当前点击的位置,相对于页面;    ev.pageX, ev.pageY

  5. 是否按下了功能键,ev.shiftKey,ev.ctrlKey,ev.altKey

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

    // 1. 获取当前触发事件类型
    console.log(ev.type);   //click
    // 2. 获取当前触发的对象
    // console.log(ev.target === document.documentElement); //html
    // console.log(ev.target); 
    console.log(ev.srcElement === document.documentElement);
    // 需要在IE8及其以下写ev.srcElement来获取对象


    // 3. 获取当前点击的位置,相对于可视区窗口;
    console.log(ev.clientX, ev.clientY);

    // 4. 获取当前点击的位置,相对于页面;
    console.log(ev.pageX, ev.pageY);
    // IE8及其之下不支持 

    // 5. 是否按下了功能键
    console.log(ev.shiftKey);   //是否按下了shift键
    console.log(ev.ctrlKey);    //是否按下了ctrl键
    console.log(ev.altKey);     //是否按下了alt键

}

事件的绑定

1. 常规的事件绑定的方法

function fn1() {
    console.log(1);
}

function fn2() {
    console.log(2);
}

box.onclick = function () {
    fn1();
}
box.onclick = function () {
    fn2();
}

缺点:这种方式事件绑定只能绑定一个事件,点击结果为2。 后面的会覆盖前面的绑定事件

2. 方式二:元素.addEventListener('不加on的事件类型',事件处理函数,是否捕获);

box.addEventListener('click', fn1, false);
box.addEventListener('click', fn2, false);
// 点击结果:1  2

可以实现多个事件的绑定,支持标准浏览器;IE8及其以下不支持;

3. IE8- 的事件绑定  元素.attachEvent('加on的事件类型',事件处理函数);

box.attachEvent('onclick', fn1);
box.attachEvent('onclick', fn2);
// 点击结果 2  1

两者的区别: 元素.addEventListener('不加on的事件类型',事件处理函数,是否捕获)

元素.attachEvent('加on的事件类型',事件处理函数)

  • 1. addEventListener 方法比attachEvent多一个是否的捕获的参数;
  • 2. addEventListener 的事件类型不需要加on,而且addEventListener 是顺序执行绑定的函数,而attachEvent是倒叙执行;
  • 3. addEventListener支持标准的浏览器,attachEvent支持IE8及其以下的浏览器;
  • 4. attachEvent事件的事件源始终指向window; addEventListener 指向当前触发事件的对象;

 

4. 绑定事件的兼容性写法

function bind(ele, event, callback) {
    if (ele.addEventListener) {
        ele.addEventListener(event, callback, false);
    } else {
        ele.attachEvent('on' + event, callback);
    }
}

// 调用
bind(box, 'click', fn1);
bind(box, 'click', fn2);
//  标准输出  1  2
//  IE8-    输出  2   1

事件的解绑

IE浏览器解绑: 元素.detachEvent(type,function);

标准浏览器解绑:元素.removeEventListener('不加on的事件类型',事件处理函数,是否捕获);

// 解绑事件的兼容性写法
function unbind(ele, event, callback) {
    if (ele.removeEventListener) {
        ele.removeEventListener(event, callback, false);
    } else {
        ele.detachEvent('on' + event, callback);
    }
}
// 绑定事件的兼容性写法
function bind(ele, event, callback) {
    if (ele.addEventListener) {
        ele.addEventListener(event, callback, false);
    } else {
        ele.attachEvent('on' + event, callback);
    }
}
// 调用
bind(box, 'click', fn1);
bind(box, 'click', fn2);
unbind(box, 'click', fn2);
// 输出结果 1

事件流

DOM事件流分为3个阶段:事件的捕获阶段,目标阶段,冒泡阶段;

捕获阶段:事件的传播是从不具体的文档传递到具体的执行事件的目标对象;

在绑定事件addEventListener时候最后一个参数为true表示捕获事件;

<div class="box1">
    <div class="box2">
        <div class="box3"></div>
    </div>
</div>

<script>
    var box1 = document.querySelector('.box1');
    var box2 = document.querySelector('.box2');
    var box3 = document.querySelector('.box3');

    function fn1() {
        console.log(1);
    }

    // 点击获取事件   捕获
    box1.addEventListener('click', fn1, true);
    box2.addEventListener('click', fn1, true);
    box3.addEventListener('click', fn1, true);
</script>

在执行过程中,单击box3元素,会执行点击事件,首先box1执行,然后将事件向下传递到box2,box3执行点击事件,所以会打印三次1。

目标阶段:通过捕获确定具体触发事件的元素;执行具体的事件函数;

冒泡阶段:事件的传递是从具体的事件目标向父元素传递直到传递给最外层的window;

在JS中,默认是冒泡事件的执行机制;

<div class="box1">
    <div class="box2">
        <div class="box3"></div>
    </div>
</div>

<script>
    var box1 = document.querySelector('.box1');
    var box2 = document.querySelector('.box2');
    var box3 = document.querySelector('.box3');

    function fn1() {
        console.log(1);
    }

    // 点击获取事件  不捕获 即使冒泡事件
    box1.addEventListener('click', fn1, false);
    box2.addEventListener('click', fn1, false);
    box3.addEventListener('click', fn1, false);

</script>

在执行过程中,单击box3元素,会执行点击事件,首先自己执行,然后将事件传递到box2,box1都会执行点击事件,所以会打印三次1。

 

阻止事件冒泡:是指子元素执行事件之后,阻止子元素再给父元素传播事件

  • 标准浏览器  ev.stopPropagation();
  • IE8- 浏览器 ev.cancelBubble=true;

兼容写法:

// 兼容写法
function stopPropagation(ev) {
    ev = ev || event;
    if (ev.stopPropagation) {
        ev.stopPropagation();
    } else {
        ev.cancelBubble = true;
    }
}

事件默认行为

给一些元素设置一些特殊的操作;  如:a标签默认会跳转页面,右击鼠标会出现菜单。当我们不在需要这些行为的时候 我们我可以阻止事件的默认行为;

阻止事件的默认行为的方式:

  1. 事件添加的事件,return false;
  2. 元素.addEventListener的方式阻止   ev.preventDefault();
  3. 元素.attachEvent 的方式阻止   ev.returnValue = false;
<a href="https://www.baidu.com">百度</a>
<script>
    // 事件的默认行为:给一些元素设置一些特殊的操作;  a标签默认会跳转页面,右击鼠标会出现菜单
    // 当我们不在需要这些行为的时候 我们我可以阻止事件的默认行为;
    // 阻止事件的默认行为的方式
    // 1. 事件添加的事件,return false;
    // 2. 元素.addEventListener的方式阻止   ev.preventDefault();
    // 3. 元素.attachEvent 的方式阻止   ev.returnValue = false;

    // var a = document.querySelector('a');
    var a = document.getElementsByTagName('a')[0];
    // a.addEventListener('click', function (ev) {
    //     ev.preventDefault();
    // });

    a.attachEvent('onclick', function (ev) {
        ev = ev || event;
        ev.returnValue = false;

    });


</script>

键盘事件

按键按下ev.keypress ev.keydown  按键抬起ev.keyup  按键对应的ASCII码值ev.keyCode, 只有在能影响用户输入的元素和window上面,才会存在键盘事件

//  可以输入任何字符
window.addEventListener('keydown', function (ev) {
    console.log(ev.keyCode);
});

// 只能输入字符类的键,不能输入功能键  如ctrl, shift...
window.addEventListener('keypress', function (ev) {
    console.log(ev.keyCode);
});

// 按键弹起时候执行
window.addEventListener('keyup', function (ev) {
    console.log(ev.keyCode);
});

滚轮事件

鼠标滚轮可以上下滚动,也会被JS监听到,称之为滚轮事件。每个浏览器的标准不同。

  1. 标准和IE8+浏览器  元素.onmousewheel=函数;
  2. 火狐浏览器  元素.addEventListener('DOMMouseScroll',执行函数, false);
// 标准和IE8+浏览器
window.onmousewheel = function () {
    console.log('滚动了');
}


// 火狐浏览器 
window.addEventListener('DOMMouseScroll', function () {
    console.log('滚动了');
}, false)

获取滚轮的滚动信息:

  1. 标准和IE8+浏览器 ev.wheelDelta;
  2. 火狐浏览器  ev.detail;
// 标准和IE8+浏览器
window.onmousewheel = function (ev) {
    ev = ev || event;
    // 向下滚动-120
    // 向上滚动120
    console.log(ev.wheelDelta);
}


// 火狐浏览器 
window.addEventListener('DOMMouseScroll', function (ev) {
    ev = ev || event;
    // 向上滚动 -3
    // 向下滚动 3
    console.log(ev.detail);
}, false)

兼容性获取滚动值:

// 兼容性写法  获取滚轮事件的信息
function wheelDelta(ev) {
   ev = ev || event;
   if (ev.wheelDelta) {
      // 标准浏览器和IE8+浏览器
      return ev.wheelDelta;
   } else {
       // 火狐浏览器 
       return ev.detail * -40;
    }
}

事件委托

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

实现:将事件添加到父元素身上,当事件发生的时候,父元素会去找对应触发事件的子元素即ev.target/ev.srcElement去处理。

好处:1、节省性能,不需要给每个子元素绑定事件;2、新添加的元素也动态的绑定了之前的事件

案例:利用事件委托,点击li,给对应的li添加背景

<ul id="list">
    <li>11111</li>
    <li>22222</li>
    <li>33333</li>
    <li>44444</li>
    <li>55555</li>
</ul>
<script>
    var ul = document.getElementById('list');
    var li = ul.getElementsByTagName('li');
    // 事件委托
    ul.onclick = function (ev) {
        var ev = ev || event;
        var target = ev.target || ev.srcElement;
        
        if (target.nodeName === 'LI') {
            target.style.backgroundColor = 'skyblue';
        }
    }
    // 新加元素
    var newLi = document.createElement('li');
    newLi.innerHTML = '新事件';
    ul.appendChild(newLi);
</script>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值