1. 典型用法
在很多场景中,只用到了 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);
2. 规则 1:隔离应用逻辑
上面的代码的第一个问题是事件处理程序包含了应用逻辑(application logic)。应用逻辑是和应用相关的功能性代码,而不是和用户行为相关的。
将应用逻辑从所有事件处理程序中抽离出来的做法是一种最佳实践,其他地方可能会触发同一逻辑。
抽离出来的另一个好处是方便测试。
对上面代码进行重构,第一步是将处理弹出框逻辑的代码放入一个单独的函数中,这个函数很可能挂载于为该应用定义的一个全局对象上。因此就有了两个方法:
// 好的写法 - 拆分应用逻辑 var MyApplication = { 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); });
3. 规则 2:不要分发事件对象
上段代码还存在一个问题,即 event 对象被无节制地分发。应用逻辑不应当依赖于 event 对象来正确完成功能。原因如下:
方法接口并没有表明哪些数据是必要的
如果想测试这个方法,必须重新创建一个 event 对象并作为参数传入
重写方法:
// 好的写法 var MyApplication = { handleClick: function(event) { this.popup(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); // 可以这样用 };
处理事件时,最好让事件程序成为接触到的 event 对象的唯一的函数。
// 好的写法 var MyApplication = { handleClick: function(event) { // 假设事件支持 DOM Level 2 event.preventDefault(); event.stopPropagation(); // 传入应用逻辑 this.popup(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); // 可以这样做 };