• Javascript事件总结


    一、事件冒泡

    1.1 事件的不同阶段

    Javascript事件在2个阶段执行:捕获与冒泡。

    如下图的Dom结构中如果指向锚点#1.1的链接被点击,则依次会触发document > body > ul > li > ul > li > a 的Click处理函数。至此完成捕获阶段。当这阶段完成,开始冒泡阶段,如图中向上箭头的顺序。事件处理函数全部触发。有兴趣可以移步这里,可以看到动态的过程。

    我们对上述代码稍加更改,假如alert,因为那个demo中的效果切换太快了,我们慢一点洗洗体会。【注:这里订阅的事件都是冒泡阶段的,也是最常用的,因为IE并不支持订阅捕获阶段的时间。比较特殊的还有Opera,常常遇到有些特性向Firefox系,偶尔会有个别特性像IE】。这篇文章也助于加深理解


    1.2 取消事件冒泡

    其实1.1的代码中已经包含了取消事件冒泡的代码。这里我们专门提出来写,使其具有更好的兼容性与美观。

    1 function stopBubble(e) {
    2 if (e && e.stopPropagation) {
    3 e.stopPropagation(); //因为传入了事件对象e,并且支持W3C标准的stopPropagation()
    4 } else {
    5 window.event.cancelBubble = true; //For IE
    6 }
    7 }

              

    【注】:我们不能简单的看到传入了事件对象就判断为非IE浏览器,因为有时候我们使用3.1的方式来绑定事件,此时极有可能也会传入一个window.event的引用。

    1.3 重载浏览器默认行为

    对于a标签等具有默认行为(如跳转到某URL)的HTML元素,我们可能想要部分a表现的有特色些,点击某a就是不跳转,可以重载其默认行为。

    function stopDetault(e) {
    if (e&&e.preventDetault) {
    e.preventDefault();
    }
    else {
    window.
    event.returnValue = false;
    }
    return false;
    }

    使用方法:

    document.getElementById("##").onclick = function (e) {
    //do sth.
    return stopDetault(e);
    }


    我们也常用下面的方式阻止默认行为,所以阻止事件处理函数本身return false也就可以理解了。

    <a href="javascript:alert('clicked');return false;">a link without redirect action</a>

      

    《Pro Javascript Techniques》[美 John Resig]一书中提到95%的情况中防止默认行为都有效,但是偶尔也会失效,因为该行为是由浏览器决定的,尤其是在文本域中防止敲击和iframe内的行为。除此之外,都应该无大碍。这是一本学习javascript的好书。推荐。

    二、 常见事件对象

    2.1 this

    this 关键字是javascript中提供对当前对象引用的变量。绑定事件时this通常指的是当前元素,但是也有例外!!初接触javascript觉得这个this有点变换莫测,难以捉摸。

    如果你的感觉也是这样,可以看看下边的文章:

    通常在绑定事件时可以这样使用this

    document.getElementById("input1").onclick = function(e){
    this.style.color="Red";
    };

      

    2.2 事件对象

    通过对下面的代码调试我们可以看到,事件对象通常包含当前键码等事件相关信息。值得一提的是IE的实现把事件对象放在一个全局变量window.event变量中保存,而其他遵从W3C标准浏览器则作为一个参数传进处理函数。

    e 

    三、 事件绑定

    各浏览器虽然支持的方式都不太一样,但是相比混乱的CSS,事件绑定还是有章可循的。IE有自己的实现方式,并且各版本统一,其他现代浏览器都按照W3C标准来实现。

    3.1 传统Dom绑定

    这种方式最简单,最有效。而且this关键词指向的是当前元素。但是缺点也不少,他们是:
    1.只能绑定一次。假如我们引用的多个类库中都对window.onload事件进行绑定,则前边的绑定将会被后边的覆盖,并且常常难以察觉。
    2.只支持订阅冒泡阶段事件。
    3.事件参数只支持非IE,虽然事件对象参数仅支持非IE浏览器,但是我们可以使用下边这种方式解决。

    <a onclick="handle(event)" href="#">link</a>

    3.2 W3C标准绑定

    这个是最开心的方式了,除IE以外的现代浏览器都支持,我们可以直接使用每个dom元素的addEventListener(eventName,handleFunc,trueOrFalse),第一个参数为订阅的事件名称,如click(没有on),第二个参数为时间处理函数,第三个参数为是否订阅事件捕获阶段。

    下面是使用addEventListener的例子

    document.getElementById("linkA").addEventListener('click', function (e) {
    alert(
    'i am clicked!');
    return stopDetault(e);
    },
    false);

    优点:
    1.支持冒泡与捕获阶段。
    2.在处理函数内部,this关键字引用当前元素。
    3.可以为同一元素的同一时间绑定多个处理函数,不会覆盖。
    缺点:
    1.IE不支持

    3.3 IE绑定

    既然上边提到IE不支持addEventListener,那么肯定要找个解决方案帮帮IE小兄弟,那就是attachEvent,虽然有很多缺点,但也够用。

    下面是attachEvent的例子

    document.attachEvent("onload", function () {
    alert(
    "i am load");
    });

      

    优点:
    1.当然这个优点是和第一种绑定方式相比的:),同一元素支持多次绑定。
    缺点:
    1.仅支持IE事件的冒泡阶段。
    2.事件处理函数内部this关键字引用了window对象。要解决这个问题请继续往下看。
    3.事件名前必须加on,当然这个只是叫法不同,也没什么大碍。
    4.只支持IE啊,这个很痛啊。

    四、 牛人们的解决方案

    Dean Edwards的方案:addEvent/removeEvent库

    这个方案比较特别。详细请移步这里

    特点:
    1 it performs no object detection
    2 it does not use the addeventListener/attachEvent methods
    3 it keeps the correct scope (the this keyword)
    4 it passes the event object correctly
    5 it is entirely cross-browser (it will probably work on IE4 and NS4)
    6 and from what I can tell it does not leak memory

      

    源码:

    function handleEvent(event) {
    var returnValue = true;
    // grab the event object (IE uses a global event object)
    event = event || fixEvent(window.event);
    // get a reference to the hash table of event handlers
    var handlers = this.events[event.type];
    // execute each event handler
    for (var i in handlers) {
    this.$$handleEvent = handlers[i];
    if (this.$$handleEvent(event) === false) {
    returnValue
    = false;
    }
    }
    return returnValue;
    };

    function fixEvent(event) {
    // add W3C standard event methods
    event.preventDefault = fixEvent.preventDefault;
    event.stopPropagation
    = fixEvent.stopPropagation;
    return event;
    };
    fixEvent.preventDefault
    = function() {
    this.returnValue = false;
    };
    fixEvent.stopPropagation
    = function() {
    this.cancelBubble = true;
    };

      

    【注】:这个方案有一个致命的东西,千万不要这样做这样会覆盖之前绑定的处理函数

    <body onload="alert('hi');"></body>

      

  • 相关阅读:
    核心数据类型
    Python入门
    [多校联考2019(Round 4 T2)][51nod 1288]汽油补给(ST表+单调栈)
    [Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理)
    [luogu5339] [TJOI2019]唱、跳、rap和篮球(容斥原理+组合数学)(不用NTT)
    用生成函数推导数列的通项公式
    [Luogu 5465] [LOJ 6435] [PKUSC2018]星际穿越(倍增)
    [BZOJ4569] [Luogu 3295] [SCOI2016]萌萌哒(并查集+倍增)
    [BZOJ4444] [Luogu 4155] [LOJ 2007] [SCOI2015]国旗计划(倍增)
    倍增好题记录
  • 原文地址:https://www.cnblogs.com/x2048/p/2133171.html
Copyright © 2020-2023  润新知