• 【译】addEventListener 第二个参数


    这是原文链接:Our Backwards DOM Event Libraries

    浏览器APIs

    先简单回顾一下各个浏览器提供了哪些绑定事件的接口。

    IE浏览器提供了element.attachEvent接口,可以绑定事件到元素上面。

    document.body.attachEvent(
        'onclick',
        function() {
            alert('body clicked');
        });
    

    其他浏览器则提供了element.addEventListener接口,我们比较熟悉的是绑定一个函数到元素上。

    document.body.addEventListener(
        'click',
        function() {
            alert('body clicked');
        },
        false);
    

    许多javascript程序员还不知道其实还可以传递一个object给addEventListener当作第二个参数,当事件被触发时,该object的handleEvent方法被调用。

    document.body.addEventListener(
        'click',
        {
            handleEvent: function() {
                alert('body clicked');
            }
        },
        false);
    

    使用object作为第二个参数有一个重要的特征:handleEvent属性的函数值只会在事件触发的时候会被调用。这意味着我们改变handleEvent属性的函数值,那么事件触发时就会调用不同的函数,也就是延迟绑定。举个例子:

    var obj = {};
    
    document.body.addEventListener('click', obj, false);
    
    // click body will error in some browsers because
    // no handleEvent method on obj
    
    obj.handleEvent = function() {alert('alpha');};
    
    // click body and see alert "alpha"
    
    obj.handleEvent = function() {alert('beta');};
    
    // click body and see alert "beta"
    
    document.body.removeEventListener('click', obj, false);
    
    // click body and see nothing
    

    跨浏览器的库

    我们实现跨浏览器的应用时,不应该因为不同浏览器的混乱的APIs写出糟糕而重复的代码,有一个好主意就是抽象出不同的APIs,实现我们自己的事件库。

    不同的库有不同的APIs,但是每个库都有一个类似下面的接口:

    LIB_addEventListener(
        document.body, 
        'click', 
        function() {
            alert('body clicked');
        });
    

    关于javascript中this的技巧

    这些库都有一个常见的问题:如果事件触发,我们调用的是视图对象的一个方法就会有问题。举个例子,比如下面的代码。handleClick方法中this的值是window对象。所以alert会显示undefined,而不是我们期待的alpha。

    function ViewObject() {
        this.data = 'alpha';
        LIB_addEventListener(
            document.body, 
            'click', 
            this.handleClick);
    }
    ViewObject.prototype.handleClick = function() {
        alert(this.data);
    };
    

    这些库中已经给出了解决办法,就是指定一个额外的参数作为this的值。这同样有利于解除事件监听。举例如下,alert会显示alpha。

    function ViewObject() {
        this.data = 'alpha';
        LIB_addEventListener(
            document.body, 
            'click', 
            this.handleClick,
            this);
    }
    ViewObject.prototype.handleClick = function() {
        alert(this.data);
    };
    ViewObject.prototype.destroy = function() {
        LIB_removeEventListener(
            document.body,
            'click',
            this.handleClick,
            this
        );
    };
    

    目前的API仍然有一个隐藏的问题:当LIB_addEventListener被调用时,监听函数就已经被绑定了。这时如果我们改变handleClick的函数值并且尝试删除监听函数,就会遇到问题。

    var vo = new ViewObject();
    
    // click on the body and see alert "alpha"
    
    vo.handleClick = function() {
        alert('beta');
    };
    
    // click on the body and still see "alpha"
    
    vo.destroy();
    
    // click on the body and still see "alpha"!
    

    还有一个问题就是我们采用面向对象的方式编程,但是我们却在关注listener functions而不是listener objects。这种不匹配是寻找更优解的线索。

    适配listener objects的API

    由于我们经常采用面向对象的方式来编程,所以很有必要让LIB_addEventListener可以接受listener objects(当然也接受listener functions)

    var obj = {
        handleEvent: function() {
            alert('click handler');
        }
    };
    LIB_addEventListener(document.body, 'click', obj);
    

    通常我们会有一个视图对象来处理各种元素的多种事件。不过需要第四个参数来指定方法名称。这仍然可以实现延迟绑定。

    var obj = {
        handleMouseDown: function() {
            alert('mouse down handler');
        },
        handleMouseUp: function() {
            alert('mouse up handler');
        }
    };
    LIB_addEventListener(document.body, 'mousedown', obj, 'handleMouseDown');
    LIB_addEventListener(document.body, 'mouseup', obj, 'handleMouseUp');
    

    通过判断第三个参数的类型,该API仍然可以接收listener functions。

    LIB_addEventListener(document.body, 'mousedown', function() {
        alert('mousedown');
    });
    

    不过我们已经没有必要使用listener functions了,因为还需要多此一举指定this object。我们可以直接使用更好的listener object。

    以上内容纯属翻译

  • 相关阅读:
    UILabel 分段改变文字颜色和字体
    ios tableView删除行
    ios 控件点击没反应的问题
    ios MJRefresh最新的一些使用
    android下水波纹效果实现
    9patch的用法,简单两句就会用了。
    有关android.support.v7.app.ActionBarActivity错误的问题
    android中fragment的使用及与activity之间的通信
    [转]CSS中继承性属性和非继承性的属性
    js中的attribute详解
  • 原文地址:https://www.cnblogs.com/3tree/p/4572206.html
Copyright © 2020-2023  润新知