javascript事件处理

事件处理的经典用法

有很多时候,我们只是用到了event所提供的信息的一小部分,例如:

// 不好的写法
function handleClick(event) {
    var popup = document.getElementById("popup");
    popup.style.left = event.clientX + "px";
    popup.style.top = event.clientY + "px";
    popup.className = "reveal";
}

addListener(element, "click", handleClick);

这段代码看起来非常简单,没有什么问题,但是实际上是不好的写法,因为这种做法有其局限性。

隔离应用逻辑

问题1:
上面的代码中,事件处理程序包含了应用逻辑。应用逻辑是和应用相关的功能性代码,而不是和用户行为相关的。如上段代码中,应用逻辑是在特定位置显示一个弹出框。将应用逻辑从事件处理程序中抽离出来是一种最佳实践,因为说不定什么时候其他地方就会触发同一段逻辑。比如,有时你需要在用户将鼠标移到某个元素上时判断是否显示弹出框,或者当按下键盘上的某个键时也作同样的逻辑判断,这样多个时间的处理程序执行了同样的逻辑,而你的代码却被不小心复制了多份
问题2:
测试时需要直接触发功能代码,而不必通过模拟对元素的点击来触发。如果将应用逻辑放置于事件处理程序中,唯一的测试方法是制造事件的触发,而调用功能性代码最好的做法就是单个的函数调用。

所以我们需要将应用逻辑和事件处理的代码拆分开:

// 好的写法 - 拆分应用逻辑
var MyApplication = {
    //handleClick方法只做一件事情,即调用MyApplication.showPopup()
    handleClick: function(event) {
        this.showPopup(event);
    },
    showPopup: function(event) {
        var popup = document.getElementById("popup");
        popup.style.left = event.clientX + "px";
        popup.style.top = event.clientY + "px";
        popup.className ="reveal";
    }
};

addListener(element, "click", function(event) {
    MyApplication.handleClick(event);
});

应用逻辑被剥离出去,对同一段功能代码的调用可以在多点发生,则不需要一定依赖于某个特定事件的触发。

不要分发事件对象

上面的代码还存在一个问题,就是event对象被无节制的分发,从handleClick,到showPopup。event对象上包含很多和事件有关的信息,而这段代码只用到了clientX,clientY。

应用逻辑不应该依赖于event对象来正确完成功能,原因如下:
1、方法接口并没有表明哪些数据是必要的。好的API一定是对于期望和依赖都是透明的。将event对象作为参数并不能告诉你event的哪些属性是有用的,用来干什么。
2、如果你想测试这个方法,你必须重新创建一个event对象并将它作为参数传入。所以,你需要确切地知道这个方法使用了哪些信息,这样才能正确地写出测试代码。

最佳的方法是让事件处理程序使用event对象来处理事件,然后拿到所有需要的数据传给应用逻辑,例如MyApplication.showPopup()只需要两个数据,x坐标和y坐标。所以我们可以这样重写下方法。

// 好的写法
var MyApplication = {

    handleClick: function(event) {
        this.showPopup(event.clientX, event.clientY);
    },

    showPopup: function(x, y) {
        var popup = document.getElementById("popup");
        popup.style.left = x +"px";
        popup.style.top = y +"px";
        popup.className = "reveal";
    }

};

addListener(element, "click", function(event) {
    MyApplication.handleClick(event);   //可以这样用
});

在测试或者代码的任意位置都可以很轻易的调用这段逻辑,比如:

MyApplication.showPopup(10, 10); 

应用逻辑不需要对event产生依赖,进而在很多地方都可以轻松的使用相同的业务逻辑,包括写测试代码。

你可能感兴趣的:(javascript事件处理)