无依赖的combobox组件(autocomplete组件)
wagang.net的首页需要一个combobox组件(autocomplete)。
QWrap里有一个:http://dev.qwrap.com/resource/js/wagang/combobox/_examples/ComboBox-Demo.html,
不过这组件开发时是依赖QWrap的。可是我只想引用一个组件,而不想附带的引入一个qwrap库。
好在QWrap堆砌库时采用了Helper规范,很多方法都是静态方法,可以独立到方法这个粒度。
所以,可以订制一个无依赖的combobox组件,以使其代码量昼量少,从而节约网络流量,提高用户体验。
OK,那就开始一次无依赖化之旅吧。
QWrap建议组件开发者使用静态方法,并且将对外引用的静态方法,统一定义在组件闭包的最前面。这一代码码,就集中体现它对QWrap的依赖。
这代码码同时也相当于一段适配代码。如果想换成依赖别一个库的,只需要将这段代码适配成其它库即可。
combobox的全部代码在这里可以看到:http://dev.qwrap.com/resource/js/wagang/combobox/combobox.js
其中适配代码即这段:
View Code
var mix=QW.ObjectH.mix,
DomU=QW.DomU,
createElement=DomU.createElement,
EventH=QW.EventH,
target=EventH.getTarget,
keyCode=EventH.getKeyCode,
preventDefault=EventH.preventDefault,
CustEvent=QW.CustEvent,
NodeH=QW.NodeH,
addClass=NodeH.addClass,
removeClass=NodeH.removeClass,
setStyle=NodeH.setStyle,
getXY=NodeH.getXY,
ancestorNode=NodeH.ancestorNode,
on=QW.EventTargetH.addEventListener,
isIe=(/msie/i).test(navigator.userAgent);
观察以上代码,可以看到,除了CustEvent这个是依赖整个模块,而不是精确到方法级别,其它的都是精确到方法级别。
CustEvent是自定义事件,该模块的js(http://dev.qwrap.com/resource/js/core/custevent.h.js),YUI压缩后约1.5K。不算大。
不过,这1.5K也可以省下来。
因为wagang.net首页所需的自定义事件,不需要多头。支持onxxx=function(){}就足够用了。
另外,getXY这个方法,由于浏览器兼容的代码太多,有好几百字节。也可以把绝对定位,改成调整dom结构的方式来定位,以节约代码。
所以,solo后的适配代码就变成这样的了:
View Code
var mix=function(des, src){
for(var i in src){
des[i] = src[i];
}
},
//DomU=QW.DomU,
createElement=function (tagName, property) {
var el = document.createElement(tagName);
if (property) {
for (var i in property) el[i] = property[i];
}
return el;
},
//EventH=QW.EventH,
target=function(e) {
e=e||window.event;
return e.target || e.srcElement;
},
keyCode=function(e) {
e=e||window.event;
return e.which || e.keyCode || e.charCode;
},
preventDefault=function(e) {
e=e||window.event;
e.preventDefault && e.preventDefault() || (e.returnValue = false);
},
//CustEvent=QW.CustEvent,
//NodeH=QW.NodeH,
hasClass=function(el, cn) {
return new RegExp('(?:^|\\s)' +cn+ '(?:\\s|$)','i').test(el.className);
},
addClass=function (el, cn) {
if (!hasClass(el, cn)) {
el.className = (el.className + ' '+cn).replace(/^\s+|\s+$/g,"");
}
},
removeClass=function (el, cn) {
if (hasClass(el, cn)) {
el.className = el.className.replace(new RegExp('(?:\\s|^)' +cn+ '(?:\\s|$)','i'),' ').replace(/^\s+|\s+$/g,"");
}
},
//setStyle=NodeH.setStyle,
//getXY=NodeH.getXY, 由于getXY的兼容代码很长,所以无依赖化时,稍稍调整下,不用位置,而改用dom结构来定位
ancestorNode=function(el,tagName){
while(el=el.parentNode){
if(el.tagName==tagName) return el;
}
return null;
},
on=function (element, name, handler) {
element.addEventListener && element.addEventListener(name, handler, false)
|| element.attachEvent && element.attachEvent('on' + name, handler);
},
isIe=(/msie/i).test(navigator.userAgent);
全部代码如下:
http://dev.qwrap.com/resource/js/wagang/combobox/_examples/ComboBox-WaGang.net.html
solo出的combobox.js部分,代码yui压后只有4.7K,足够满足要求了。
以上,只是大略记述QWrap组件无依赖化的过程。
由于QWrap框架用helper规范来堆砌库,所以基于helper开发出来的组件也很容易改装成无依赖的组件。
这也是QWrap的初衷之一:服务于组件开发者,让他们依赖QWrap开发组件,而发布出无依赖的组件。
附:
以上代码中,所说到的combobox组件,来自:http://dev.qwrap.com/resource/js/wagang/combobox/_examples/ComboBox-Demo.html
独立后的combobox组件,应用于wagang.net主页:http://www.wagang.net
更多wagang组件,参见:http://dev.qwrap.com/resource/js/wagang/_index.html