从设计的层面上来考下,这种事件组合的方式是如何实现?有什么优势?
设计一:
tAjax({ url: "php.html", complete: function(data) { console.log(data) } })
如果要实现这种接口调用那么我们就需要封装下代码,把回调通过实参传递。
var tAjax = function(config) { //参考右图设计一 }
这样设计可以看做类似工厂模式的封装,好处不用多说在工厂模式里面包含了对象的创建等必要的逻辑,客户端根据传参选择动态的实例化相对的处理,对于客户端来去除了具体的依赖,当然 tAjax 你也可以看作一个外观模式提供的接口,其实就是隐藏了具体的复杂逻辑,提供一个简单的接口,从而降低耦合。
设计二:
tAjax({ url: "php.html", complete: function(data) { console.log(data) } }).done(function(data){ console.log(data) })
在之前加入了一个 done 链式处理,当然这里 done,其实是 deferred 的一个成功处理通知,如果之前没有接触,大家去了解一下关于 deferred 的概念,我们知道 jQuery 实现了链式,实现的原理无法就是返回本身对象的引用。
var ajax = tAjax({ url: "php.html", complete: function(data) { console.log(data) } }) ajax.done(function(){ //......... })
以上是分离的情况下,如果要合并成一条链式处理,只要在上一个方法中返回 this 即可。
var tAjax = function(config) { ///参考右图设计二 return { done: function(ourfn) { doneFn = ourfn; } } }
我们返回了一个 done 对象,这里一样要是对象,因为链式的原因我们看外部指定了内部的 done,从而把外部函数给引用到内部的 doneFn 上缓存起来 xhr.staturs 成功后一起执行,当然这种设计是有问题的,如果在 done 之后我再链式就肯定不行,因为对象的引用错了,那么 jQuery 是如何处理?
设计三:提供 document 对象的全局处理
$(document).ajaxComplete(function() { console.log('ajax请求成功') }) tAjax({ url: "php.html", complete: function(data) { console.log(data) } }).done(function(data){ console.log(data) })
<!doctype html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>接口设计的优劣</title> </head> <body> <script type="text/javascript"> //伪代码,仅做参考 //设计一 var tAjax1 = function(config) { var url = config.url; var complete = config.complete; var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); xhr.open('post', url); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { complete(xhr.responseText); } } } xhr.send(); } //设计二 var tAjax2 = function(config) { var doneFn; var url = config.url; var complete = config.complete; var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); xhr.open('post', url); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { doneFn(xhr.responseText); complete(xhr.responseText); } } } xhr.send(xhr.responseText); return { /** * 返回一个done对象 */ done: function(ourfn) { doneFn = ourfn; } }; } </script> </body> </html>