JS里关于事件的常被考察的知识点:事件流、事件广播、原生JS实现事件代理

1、JS里面的事件流

  DOM2级事件模型中规定了事件流的三个阶段:捕获阶段、目标阶段、冒泡阶段,低版本IE(IE8及以下版本)不支持捕获阶段

  捕获事件流:Netscape提出的事件流,即事件由页面元素接收,逐级向下,传播到最具体的元素。

  冒泡事件流:IE提出的事件流,即事件由最具体的元素接收,逐级向上,传播到页面。

  关于js事件,这里有一篇非常详细的介绍,可以看下:http://www.cnblogs.com/hyaaon/p/4630128.html

2、IE和W3C不同绑定事件解绑事件的方法有什么区别,参数分别是什么,以及事件对象e有什么区别

  绑定事件:

  W3C:target.addEventListener(event, listener, useCapture);

  event —— 事件类型;

  listener —— 事件触发时执行的函数;

  useCapture —— 指定事件是否在捕获或冒泡阶段执行,为true时事件句柄在捕获阶段执行,为false(默认false)时,事件句柄在冒泡阶段执行。

btn.addEventListener(‘click‘,function(){
    //do something...
},false)

  对应的事件移除:

removeEventListener(event,function,capture/bubble);

  IE:target.attachEvent(type, listener);

  type - 字符串,事件名称,含“on”,比如“onclick”、“onmouseover”、“onkeydown”等。

  listener —— 实现了 EventListener 接口或者是 JavaScript 中的函数。

btn.attachEvent(‘onclick‘,function(){
    //do something...
})

  对应的事件移除:

detachEvent(event,function);

3、事件的委托(代理 Delegated Events)的原理以及优缺点

  委托(代理)事件是那些被绑定到父级元素的事件,但是只有当满足一定匹配条件时才会被挪。这是靠事件的冒泡机制来实现的,

  优点是:

  (1)可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒

  (2)可以实现当新增子对象时无需再次对其绑定事件,对于动态内容部分尤为合适

  缺点是:

  事件代理的应用常用应该仅限于上述需求下,如果把所有事件都用代理就可能会出现事件误判,即本不应用触发事件的被绑上了事件。

var toolbar = document.querySelector(".toolbar");
toolbar.addEventListener("click", function(e) {
  var button = e.target;
  if(!button.classList.contains("active"))
    button.classList.add("active");
  else
    button.classList.remove("active");
});

4、手写原生js实现事件代理,并要求兼容浏览器

// 简单的事件委托
function delegateEvent(interfaceEle, selector, type, fn) {
    if(interfaceEle.addEventListener){
        interfaceEle.addEventListener(type, eventfn);
    }else{
        interfaceEle.attachEvent("on"+type, eventfn);
    }

    function eventfn(e){
        var e = e || window.event;
        var target = e.target || e.srcElement;
        if (matchSelector(target, selector)) {
            if(fn) {
                fn.call(target, e);
            }
        }
    }
}
/**
 * only support #id, tagName, .className
 * and it‘s simple single, no combination
 */
function matchSelector(ele, selector) {
    // if use id
    if (selector.charAt(0) === "#") {
        return ele.id === selector.slice(1);
    }
    // if use class
    if (selector.charAt(0) === ".") {
        return (" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
    }
    // if use tagName
    return ele.tagName.toLowerCase() === selector.toLowerCase();
}

//调用
var odiv = document.getElementById("oDiv");
delegateEvent(odiv,"a","click",function(){
    alert("1");
})

5、事件如何派发也就是事件广播(dispatchEvent)

  一般我们在元素上绑定事件后,是靠用户在这些元素上的鼠标行为来捕获或者触发事件的,或者自带的浏览器行为事件,比如click,mouseover,load等等,有些时候我们需要自定义事件或者在特定的情况下需要触发这些事件。这个时候我们可以使用IE下fireEvent方法,高级浏览器(chrome,firefox等)有dispatchEvent方法

  IE下的例子:

//document上绑定自定义事件ondataavailable
document.attachEvent(‘ondataavailable‘, function (event) {
    alert(event.eventType);
});
var obj=document.getElementById("obj");
//obj元素上绑定click事件
obj.attachEvent(‘onclick‘, function (event) {
    alert(event.eventType);
});
//调用document对象的createEventObject方法得到一个event的对象实例。
var event = document.createEventObject();
event.eventType = ‘message‘;
//触发document上绑定的自定义事件ondataavailable
document.fireEvent(‘ondataavailable‘, event);
//触发obj元素上绑定click事件
document.getElementById("test").onclick = function () {
    obj.fireEvent(‘onclick‘, event);
};

  高级浏览器(chrome,firefox等)的例子:

//document上绑定自定义事件ondataavailable
document.addEventListener(‘ondataavailable‘, function (event) {
    alert(event.eventType);
}, false);
var obj = document.getElementById("obj");
//obj元素上绑定click事件
obj.addEventListener(‘click‘, function (event) {
    alert(event.eventType);
}, false);
//调用document对象的 createEvent 方法得到一个event的对象实例。
var event = document.createEvent(‘HTMLEvents‘);
// initEvent接受3个参数:
// 事件类型,是否冒泡,是否阻止浏览器的默认行为
event.initEvent("ondataavailable", true, true);
event.eventType = ‘message‘;
//触发document上绑定的自定义事件ondataavailable
document.dispatchEvent(event);
var event1 = document.createEvent(‘HTMLEvents‘);
event1.initEvent("click", true, true);
event1.eventType = ‘message‘;
//触发obj元素上绑定click事件
document.getElementById("test").onclick = function () {
    obj.dispatchEvent(event1);
};

原文地址:https://www.cnblogs.com/goloving/p/9375079.html

时间: 2024-10-11 13:35:53

JS里关于事件的常被考察的知识点:事件流、事件广播、原生JS实现事件代理的相关文章

移动端三合一瀑布流插件(原生JS)

没有前言,先上DEMO(手机上看效果更佳)和 原码. 瀑布流形式的图片布局方式在手机等移动端设备上运用广泛,比较常见的是下面前两种: 一.等宽等高 这种形式实现起来非常容易,这里就不再多说. 二.等宽不等高 这种形式算是比较正统的瀑布流布局形式,关于如何实现的请参考之前的一篇博文——jQuery瀑布流详解. 三.等高不等宽 在之前的工作中接触到了这种形式的瀑布流,它的主要特点是:同一行的两张图片高度相等,宽度不等,且宽高比与原图近乎一致(没有拉伸变形).但是不同行的图片高度不一定相等,下面就介绍

放弃jQuery,使用原生js吧!

转自:http://itakeo.com/blog/2015/07/28/nojq/ 随着IE6.7.8的逐渐淘汰,HTML5的兴起,以及侧重点放在了移动端,jQuery可能变的不在那么重要,原生一样很好用.下面介绍几个原生替换jq的方法. 获取元素 JQuery $('.xxx'); //class获取 $('#xxx'); //id获取 $('.xxx.ccc'); //同时包含xxx和ccc $('.xxx,.zzz'); //多选 $('.xxx div'); //子类 $('.xxx

原生js仿jquery一些常用方法

原生js仿jquery一些常用方法 下面小编就为大家带来一篇原生js仿jquery一些常用方法(必看篇).小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 最近迷上了原生js,能不用jquery等框架的情况都会手写一些js方法,记得刚接触前端的时候为了选择器而使用jquery...现在利用扩展原型的方法实现一些jquery函数: 1.显示/隐藏 //hide() Object.prototype.hide = function(){ this.style.displa

原生JS实现简单富文本编辑器2

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

原生JS封装Ajax插件(同域&amp;&amp;jsonp跨域)

抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正确的地方,还望指正^_^ 一.Ajax核心,创建XHR对象 Ajax技术的核心是XMLHttpRequest对象(简称XHR),IE5是第一款引入XHR对象的浏览器,而IE5中的XHR对象是通过MSXML库中的一个ActiveX对象实现的,因此在IE中可能有3个版本,即MSXML2.XMLHttp.

用原生js封装轮播图

原生js封装轮播图 对于初学js的同学来说,轮播图还是一个难点,尤其是原生js封装轮播图代码,下面是我之前做的一个轮播图项目中封装好的一些代码,有需要的同学可以看一下,有什么不懂的可以看注释,注释看不懂的可以直接私信我 slide.js /* * 轮播图 */ function Slide(elem, ms, d, ind){ this.el = elem; this.w = parseInt(getStyle(elem, "width")); this.h = parseInt(ge

原生js实现上拉加载

原生js实现上拉加载:https://www.cnblogs.com/xinsir/p/10314694.html 原生js实现上拉加载其实超级简单,把原理整明白了你也会,再也不用去引一个mescroll啦~ 好了,废话不多说,开始进入正题:上拉加载是怎么去做的,原理就是监听滚动条滑到页面底部,然后就去做一次请求数据.那么只要我们对滚动监听即可. 现在,让我们来看代码: window.onscroll = function () { var scrollH = document.document

理解 Node.js 里的 process.nextTick()

有很多人对Node.js里process.nextTick()的用法感到不理解,下面我们就来看一下process.nextTick()到底是什么,该如何使用. Node.js是单线程的,除了系统IO之外,在它的事件轮询过程中,同一时间只会处理一个事件.你可以把事件轮询想象成一个大的队列,在每个时间点上,系统只会处理一个事件.即使你的电脑有多个CPU核心,你也无法同时并行的处理多个事件.但也就是这种特性使得node.js适合处理I/O型的应用,不适合那种CPU运算型的应用.在每个I/O型的应用中,

我这样理解js里的this

关于this,是很多前端面试必考的题目,有时候在网上看到这些题目,自己试了一下,额,还真的错了!在实际开发中,也会遇到 this 的问题(虽然一些类库会帮我们处理),例如在使用一些框架的时候,例如:knockout,有时候不明白为什么不直接使用this,而要把 this 作为参数传入. 接下来你谈谈我对它的理解,也作为一个笔记,方便以后参阅.有不对的地方,欢迎指出批评. 1. 不像C#,this一定是指向当前对象.js的this指向是不确定的,也就是说是可以动态改变的.call/apply 就是