event target_$(event.target);-程序员宅基地

event target

Posted on 2018-03-09

| In Javascript

事件

页面与用户之间的交互是通过事件完成的。事件是用户自身的操作或者浏览器自身的一些动作。比如常见的用户的点击,浏览器load事件。在事件发生的过程中会记录一些用户的操作信息或者浏览器的动作信息。学习事件需要了解事件的机制(冒泡、捕获),不同浏览器对dom事件的写法以及delegate,onload、domReady等等。

DOM处理事件的方式,可以写在标签中执行。也可以通过js添加属性事件例如 onclick,或者事件监听方式

<div onclick = "fn()"></div>
divDom.onclick = fn;
divDom.addEventListener('click', fn);

事件流

页面上执行事件时候有一个顺序

DOM流中当点击了一个div,实际上也相当于点击了body、html、window。在非IE给dom添加监听事件的方法最后一个参数代表是否捕获,默认不捕获。还是参照上边的图做一个简单的说明

divDom.addEventListener('click', function(){ console.log('div1')}, false)document.body.addEventListener('click', function(){ console.log('body')}, false)document.documentElement.addEventListener('click', function(){ console.log('document')}, false)window.addEventListener('click', function(){ console.log('window')}, false)divDom.addEventListener('click', function(){ console.log('div2')}, true)document.body.addEventListener('click', function(){ console.log('body')}, true)document.documentElement.addEventListener('click', function(){ console.log('document')}, true)window.addEventListener('click', function(){ console.log('window')}, true)

当点击了 div 会优先触发父元素的捕获事件依次向子元素执行,其次在从子元素依次执行不捕获事件(冒泡阶段)。针对事件源,哪个事件写在前优先执行哪个事件。

阻止冒泡。有时候可能我们不需要事件产生冒泡,这个时候就要断绝父子关系了js中有两种方式。但是冒泡也是有好处的,不要觉得冒泡不好例如delegate 就是利用的冒泡。

event.cancelBubble = true;   // 非标准  无兼容问题 推荐使用(真的是比另外一个好记多了)
event.stopPropagation();     // 标准

事件监听

IE浏览器的监听方式和其它浏览器不同 attachEvent addEventListener 两种。

el.attachEvent(type, fn)
el.addEventListener(type, fn, boolean);

两者的 type 有一点区别 IE的事件和属性添加的一样 on+type ,跨浏览器事件处理

var eventHandle = function(obj, type, fn){
    if(obj.addEventListener){
        obj.addEventListener(type, fn, false);
    }else if(obj.attachEvent){
        obj.attachEvent('on'+type, fn);
    }else{
        obj[on+'type'] = fn;
    }
}

虽然可以跨浏览器使用这个方法。但是有一个问题,IE中绑定事件的传入的fn,this 指向不是当前的 obj 。

<div id="box">点我</div>
<script>
    function fn(){alert(this.innerText)};
    box.attachEvent('onclick', fn);  // undefined
</script>

嫌弃IE可能这一点占了很大一部分,可以通过 call apply bind 来改变 this 的指向。但是低版本的IE不支持bind 绑定。修改一下

var eventHandle = function(obj, type, fn){
    if(obj.addEventListener){
        obj.addEventListener(type, function(){
            fn.apply(obj, arguments)
        }, false);
    }else if(obj.attachEvent){
        obj.attachEvent('on'+type, function(){
            fn.apply(obj, arguments);
        });
    }else{
        obj[on+'type'] = fn;
    }
};

很好,但是有点觉得这个东西有点重复把fn在提取出来

var eventHandle = function(obj, type, fn){
    var handle = function(){
        fn.apply(obj, arguments)
    }
    if(obj.addEventListener){
        obj.addEventListener(type, handle, false);
    }else if(obj.attachEvent){
        obj.attachEvent('on'+type, handle);
    }else{
        obj[on+'type'] = fn;
    }
    return handle
};

基本上没有问题, 事件绑定之后可能回去解除绑定的函数,这个写法找不到对应的函数,需要把这个函数return出去。所以重新写一个事件处理函数添加解除绑定的方法。为了形成一个完整的处理函数,里边的每一个功能分开

var eventHandle = function(){
    var fire = function(el, type, fn){
        var handle = function(){
            fn.apply(obj, arguments)
        }
        if(obj.addEventListener){
            obj.addEventListener(type, handle, false);
        }else if(obj.attachEvent){
            obj.attachEvent('on'+type, handle);
        }else{
            obj['on'+ type] = fn;
        }
        return handle;
    }

    var remove = function(el, type, handle){
        if(obj.removeEventListener){
            obj.removeEventListener(type, handle, false);
        }else if(obj.deatchEvent){
            obj.deatchEvent('on'+type, handle);
        }else{
            obj[on+'type'] = null;
        }
    }
    return {
        fire: fire,
        remove: remove
    }
}();

// test
var handle = eventHandle.fire(boxDom, 'click', function(){
    alert(this.innerText);
})
eventHandle.remove(boxDom, 'click', handle);



~function($){
    if(document.addEventListener){
        $.addEvent = function(el,type,callBack){
            el.addEventListener(type,callBack,false);
            el[type+'callBack'] = el[type+'callBack'] || [];
            el[type+'callBack'].push(callBack);
            return callBack;
        }
        $.off = function(el,type,fn){
            if(typeof fn != 'undefined'){
                el.removeEventListener(type,fn,false);
            }else{
                el[type+'callBack'].forEach(function(item){
                    el.removeEventListener(type,item);
                })
            }
        };
    }else{
        $.attachEvent = function(el,type,callBack){
            var bound = function(){
                return fn.apply(el,arguments);
            }
            el.attachEvent('on'+type,bound);
            return bound;
        };
        $.off = function(el,type,fn){
            el.detachEvent('on'+type,fn);
        };
    };
}(window);

另外尝试,因为事件监听的方式不会产生覆盖,如果想一次性清除所有的相同类型的事件可以采用上边的写法。都是简单的尝试,更多的细节也可以去查看一下jq的源码,其中对事件的处理方式很多东西值得学习。

事件对象

在DOM上触发某个事件的时候会产生一个事件对象,用来记录与这个事件相关信息。非IE中这个事件对象存在于绑定函数的参数中,IE则不能直接使用这个参数而是通过访问window对象底下的event对象。

el.onclick = function(e){
    e = e || window.event;
    alert(e);
};

阻止冒泡也是通过事件对象底下属性和方法去做到的。事件对象还能做什么呢?

鼠标位置可以用来做很多事情。IE与非IE鼠标位置的获取不同 clientX/Y pageX/Y

区别:pageX/Y 不兼容ie9-。获取的值clientX/Y获取到可视区的距离,pageX/Y获取到浏览器的绝对距离,但是如果要在IE下获取到距离浏览器的绝对距离就需要手写了。

function posXY(e){
    e = e || event;
    var pos = {x:0, y:0};
    if(e.pageX){
        pos.x = e.pageX;
        pos.y = e.pageY;
    }else{
        pos.x = e.clientX + document.documentElement.scrollLeft;
        pos.y = e.clientY + document.documentElement.scrollTop;
    }
    return pos;
}

阻止默认事件

如果调用事件的对象 cancelable 的值为true,那就表明存在默认事件。a链接,表单提交,浏览器滚动条,有时候都需要阻止其中的默认事件 w3c的方法是e.preventDefault(),IE则是使用 e.returnValue = false js中使用return false 也可以做到当然只是高级浏览器。

键码

玩过游戏的都知道键盘上我们可以控制游戏人物的方向,键盘事件中 event.keyCode 用来监听按了哪一个按键,查询对应的键码就知道按下了哪一个键。

document.onkeydown = function(e){
    e = e || event;
    if(e.keyCode == 13){  // 回车键
        // 操作
    }
}

鼠标按键

// 阻止右键菜单
document.oncontextmenu = function(){
    return false;
}
// 自定义右键菜单  0--左键  1--滚轮  2--右键
document.onmousedown = function(e){
    e = e || event;
    var x = e.pageX;
    var y = e.pageY;
    if(e.button == 2){
        var divDom = document.createElement("div");
        with(divDom.style){
            width = '100px';
            height = '100px';
            background = 'red';
            position = 'absoulte';
            left = x + 'px';
            top = y + 'px';
        } 
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42160596/article/details/81585168

智能推荐

schedulewithfixeddelay-程序员宅基地

文章浏览阅读2.4w次,点赞4次,收藏11次。scheduledfuture schedulewithfixeddelay(runnablecommand, longinitialdelay, longdelay, ..._schedulewithfixeddelay

Java实现的计算器输入框及代码示例-程序员宅基地

文章浏览阅读429次。展开全部||这有什么难的 我把我那个代码给你算了 是SWing写的import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax..._java输入框计算器

数据库复习之索引和explain_数据库 复习 index-程序员宅基地

文章浏览阅读167次。索引查看表中已经存在 index:show index from table_name;创建和删除索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引。删除索引可以利用ALTER TABLE或DROP INDEX语句来实现。(1)使用ALTER TABLE语句创建索引。语法如下:alter table tab..._数据库 复习 index

GC日志分析_已追加形式gc日志-程序员宅基地

文章浏览阅读2.1w次,点赞17次,收藏57次。通过 -XX:+PrintGCDetails 启用日志GC (minor )日志Full GC 日志_已追加形式gc日志

2019cyberCTF MIsc The World_cyberfl0wer-程序员宅基地

文章浏览阅读337次。别问为什么这么久没更新博客 问就是懒。杭电的题目,这个肝的很有意思所以记下来题目下来是一张图 给了提示说有三条线索,两个hint分别是,数字从小到大做,以及最后一关取前16位。下载后是张图片,惯例binwalk。发现有隐藏文件,这里选择foremost(别问为什么用foremost,因为这个题目用binwalk -e就是个坑),总之分解出来后会有三个文件,一张jpg,一个zip,一个mp3..._cyberfl0wer

物联网智能家居实训系统_物联网智能家居实验报告-程序员宅基地

文章浏览阅读1.9k次,点赞3次,收藏12次。物联网智能家居实训系统产品型号和技术规格系统概述物联网智能家居实训系统,以智能家居行业为背景,对智能家居中多个子系统进行安装调试操作,培养学生的工程技能,使其能够搭建相对复杂的物联网应用系统,并对工程岗位的工作有初步认知。该系统综合运用传感器采集、无线传感器网络、自动控制、嵌入式系统开发、网络通信、Android移动应用开发、Web应用开发等物联网技术,将家居环境传感器、终端控制器、家用电器、家居网关等集成,实现家居生活环境的自动监测、自动调节、安防报警、视频监控、远程监控等功能,贴近实际_物联网智能家居实验报告

随便推点

5G基本概念及其发展概况_5g/nrrrrqc概述cwq-程序员宅基地

文章浏览阅读1.7k次。一、5G基本概念  第五代移动电话行动通信标准,也称第五代移动通信技术,外语缩写:5G。也是4G之后的延伸,正在研究中,5G网络的理论下行速度为10Gb/s(相当于下载速度1.25GB/s)[4]。  诺基亚与加拿大运营商BellCanada合作,完成加拿大首次5G网络技术的测试。测试中使用了73GHz范围内频谱,数据传输速率为加拿大现有4G网络的6倍。鉴于两者的合作,外界分析加拿大很有可能将在5年内启动5G网络的全面部署。  由于物联网尤其是互联网汽车等产业的快速发展,其对网络速度有着更高的要求,._5g/nrrrrqc概述cwq

关于LTspice官网上的仿真电路打不开_ltspice:fatal error: no analysis request found.-程序员宅基地

文章浏览阅读599次。关于LTspice官网文件打不开?_ltspice:fatal error: no analysis request found.

Thymeleaf select 使用 和多select 级联选择-程序员宅基地

文章浏览阅读2.1k次。1.使用select 并且回绑数据;页面:状态:<select name="status" th:field="*{status}" id="idstatus" class="input-select" th:value="*{status}"><option value="">--请选择--</option><option th:ea..._thymeleaf select

springboot集成sharding-jdbc_springboot整合sharding-jdbc-程序员宅基地

文章浏览阅读1.9k次。一个比较简单的集成,只用到了分库,没有分表。pom完整依赖:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> &_springboot整合sharding-jdbc

Spring获取ApplicationContext的几种方法_java 静态类获取spring appliactioncontext-程序员宅基地

文章浏览阅读681次。Spring获取ApplicationContext的几种方法1.ApplicationContext简介2.获取方法2.1 通过Spring提供的工具类WebApplicationContextUtils获取2.2 初始化时保存ApplicationContext对象2.3 继承自抽象类ApplicationObjectSupport2.4 继承自抽象类WebApplicationObjectS..._java 静态类获取spring appliactioncontext

Quick-CUDA开发/移植工具介绍-程序员宅基地

文章浏览阅读159次。如果你想开发CUDA应用软件,你可以选择1. 努力学习CUDA开发技巧, 以及相关的并行技巧 ‧ 深入掌握 SM/SP、thread、内存/显存之间关系,以及数据交换各种深层技术 ‧ 针对不同状况进行 3~5 阶段的深度CUDA并行优化 ‧ 当CUDA 版本更新、GPU架构改变时,需自行重新改写代码2. 使用快速的 CUDA 开发、移植工具...

推荐文章

热门文章

相关标签