zoukankan      html  css  js  c++  java
  • 【译】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。

    以上内容纯属翻译

  • 相关阅读:
    geoserver发布地图服务WMTS
    geoserver发布地图服务WMS
    geoserver安装部署步骤
    arcgis api 3.x for js 入门开发系列十四最近设施点路径分析(附源码下载)
    arcgis api 3.x for js 入门开发系列十三地图最短路径分析(附源码下载)
    cesium 之自定义气泡窗口 infoWindow 后续优化篇(附源码下载)
    arcgis api 3.x for js 入门开发系列十二地图打印GP服务(附源码下载)
    arcgis api 3.x for js 入门开发系列十一地图统计图(附源码下载)
    arcgis api 3.x for js 入门开发系列十叠加 SHP 图层(附源码下载)
    arcgis api 3.x for js入门开发系列九热力图效果(附源码下载)
  • 原文地址:https://www.cnblogs.com/3tree/p/4572206.html
Copyright © 2011-2022 走看看