做者首先给了个咱们一个处理事件的方法。看起来也没啥俩样,不事后来给出的优化方法很值得学习:app
// 很差的写法
function handleClick(event) { var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; pop.className = "reveal"; } // 一个事件绑定事件(第5章的)
addListener(element, "click", handleClick);
做者补充了一句:这段代码只用到了event对象的俩个属性:clientX和clientY。在将元素显示在页面里以前先用这俩个属性给它作定位。函数
尽管这段代码开起来很是简单且没有什么问题,但其实是很差的写法,由于这种作法有其局限性。学习
首先,这段代码的应用逻辑(application logic)和用户行为混在一块儿了。就是说:这个事件的处理方法和点击事件连在一块儿了,从而致使耦合度的提升。测试
这个状况其余语言中也很常见,一般咱们将处理逻辑封装起来从而能够把代码重用,因此做者提出了很重要的思想:优化
将应用逻辑从全部事件处理程序中抽离出来的作法是一种最佳实践。this
将代码重构一下变成这样:spa
// 好的写法 - 拆分应用逻辑
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); });
上述代码还存在一个问题:即event对象被无节制地分发。event对象上包含不少的和事件相关的额外信息,而这段代码只用到了其中俩个而已。code
做者提供了俩个理由:对象
最佳的办法是让事件处理程序使用event对象来处理事件,而后拿到全部须要的数据传给应用逻辑。blog
将代码重构一下:
// 好的写法
var MyApplication = { handleClick: function(event){ this.showPopUp(event.clientX,event.clientY); // 这里标明所期待传入的参数
}, showPopUp: function(x,y) { // 这里的参数就再也不依赖event咯
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对象的惟一的函数。事件处理程序应当在进入应用逻辑以前针对event对象执行任何须要的操做,包括阻止默认事件或阻止事件冒泡,都应当直接包含在事件程序中。
// 好的写法
var MyApplication = { handleClick: function(event){ // 假设事件支持DOM Level2
event.preventDefault(); event.stopPropagation(); // 传入应用逻辑
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"; } };
在这段代码中,MyApplication.handleClick()是事件处理程序,所以它在数据传入应用逻辑以前调用 event.preventDefault()和 event.stopPropagation(),这清楚的展现了事件处理程序和应用逻辑之间的分工。由于应用逻辑不须要对event产生依赖,进而在不少地方均可以轻松地使用相同的业务逻辑,包括写测试代码。