QWrap简介之:dom_retouch --- NodeW 勇士装甲

在《QWrap简介之:NodeW ---Node包装
一文中已介绍过NodeW,不过,那是他没配装备的样子。
NodeW是一个勇士的坯子,需要装甲以后才能成为真正的勇士。
QWrap已经有很多"甲",包括:NodeH、EventTargetH、JssTargetH、ArrayH。
可以这么说:由Helper堆砌起来的QWrap只是一个工具集,与是YUI2类似。我们用工具也可以来做事,不过显得有些生硬。我们还可以请一个勇士来,让勇士来使用这些工具,而我们来指挥勇士。
js/dom/dom_retouch.js的一个主要任务,就是为NodeW这个勇士装甲。

好的,我们明白了这些,那我们就来看所推荐的core_retouch吧。其中与NodeW有关的一段如下
NodeW.pluginHelper(NodeH, NodeC.wrapMethods, NodeC.gsetterMethods);
NodeW.pluginHelper(EventTargetH,
'operator');
NodeW.pluginHelper(JssTargetH, NodeC.wrapMethods, {jss: [
'', 'getJss', 'setJss']});

var ah = QW.ObjectH.dump(QW.ArrayH, NodeC.arrayMethods);
ah
= methodize(ah);
ah
= rwrap(ah, NodeW, NodeC.wrapMethods);
mix(NodeW.prototype, ah);


前三句是为NodeW装备NodeH、EventTargetH、JssTargetH。
后面几句是为NodeW装备ArrayH,使NodeW的ArrayLike的功能从ArrayH中获得。
这里用到了两个之前没有介绍过的东西。NodeW.pluginHelper、NodeC。它们分别是什么?

NodeW.pluginHelper是NodeW的一个静态方法,作用是“在NodeW中植入一个针对Node的Helper”,它的代码也很简单,如下:

/**
* 在NodeW中植入一个针对Node的Helper
* @method pluginHelper
* @static
* @param {helper} helper 必须是一个针对Node(元素)的Helper
* @param {string|json} wrapConfig wrap参数
* @param {json} gsetterConfig (Optional) gsetter 参数
* @return {NodeW}
*/

NodeW.pluginHelper
= function(helper, wrapConfig, gsetterConfig) {
var HelperH = QW.HelperH;

helper
= HelperH.mul(helper, wrapConfig); //支持第一个参数为array

var st = HelperH.rwrap(helper, NodeW, wrapConfig); //对返回值进行包装处理
if (gsetterConfig) {//如果有gsetter,需要对表态方法gsetter化
st = HelperH.gsetter(st, gsetterConfig);
}

mix(NodeW, st);
//应用于NodeW的静态方法

var pro = HelperH.methodize(helper, 'core');
pro
= HelperH.rwrap(pro, NodeW, wrapConfig);
if (gsetterConfig) {
pro
= HelperH.gsetter(pro, gsetterConfig);
}
mix(NodeW.prototype, pro);
};

以下面的一个简单例子来说明它的功能:
var myHelper={
getValue:
function(el){return el.value;},
setValue:
function(el,value){el.value=value;}
};
NodeW.pluginHelper(
myHelper,
{
getValue:
'getter_first_all',
setValue:
'operator'
}, {
val: [
'getValue', 'setValue']
}
);

它们产出的结果是:
NodeW.prototype多出了以下系列方法:
getValue,用法如:W('input').getValue(); //返回第一个input的value值
getValueAll,用法如:W('input').getValueAll(); //返回所有input元素的值组成的组
setValue,用法如:W('input').setValue(1); //所有input赋值成1
val,是一个gsetter,即getter_first与setter的混合体,由参数个数决定是getter_first还是setter。用法如:
    W('input').val(); //返回第一个input的value值
    W('input').val(1); //所有input赋值成1
当然,作为setter时,会返回本身,可以继续操作。例如:
W('input').val(1).val();//先设value再获取第一个value
除了上面的类似于jquery的用法外,还会产生静态用法。静态用法在某些时候会省写一个括号,例如,假设我们已以知道el=某INPUT原素,以下两行会有同样的功能:
W.val(el);
W(el).val();
有的同学可能会认为用法太多让人烦恼,那可以忽略掉静态用法。

以上,是否对NodeH.pluginHelper有了感性的认识?
那我们再回顾一下pluginHelper做了哪些事:
1 mul化:让myHelper里不支持参数为数组的getValue/setValue支持数组了。
2 分静态和原型不同处理,其中
  静态渲染:先按配置决定是否包装与包装形式,再按配置让某些方法配对形成gsetter,再把这些静态函数渲染到NodeW上。
  原型渲染:先方法化,再按配置决定是否包装与包装形式,再按配置让某些方法配对形成gsetter,再把这些方法渲染到NodeW.prototype上。

上面都讲到了NodeC配置,那再看一下js/dom/node.c.js
View Code
(function() {
var queryer = 'queryer',
operator
= 'operator',
getter_all
= 'getter_all',
getter_first
= 'getter_first',
getter_first_all
= 'getter_first_all';

QW.NodeC
= {
getterType: getter_first,
arrayMethods:
'map,forEach,toArray'.split(','),
//部分Array的方法也会集成到NodeW里
wrapMethods: {
//queryer “返回值”的包装结果
//operator 如果是静态方法,返回第一个参数的包装,如果是原型方法,返回本身
//getter_all 如果是array,则每一个执行,并返回
//getter_first 如果是array,则返回第一个执行的返回值
//getter_first_all 同getter,产出两个方法,一个是getterFirst,一个是getterAll
//NodeH系列
g: queryer,
one: queryer,
query: queryer,
getElementsByClass: queryer,
outerHTML: getter_first,
hasClass: getter_first,
addClass: operator,
removeClass: operator,
replaceClass: operator,
toggleClass: operator,
show: operator,
hide: operator,
toggle: operator,
isVisible: getter_first,
getXY: getter_first_all,
setXY: operator,
setSize: operator,
setInnerSize: operator,
setRect: operator,
setInnerRect: operator,
getSize: getter_first_all,
getRect: getter_first_all,
nextSibling: queryer,
previousSibling: queryer,
ancestorNode: queryer,
parentNode: queryer,
firstChild: queryer,
lastChild: queryer,
contains: getter_first,
insertAdjacentHTML: operator,
insertAdjacentElement: operator,
insert: operator,
insertTo: operator,
appendChild: operator,
insertSiblingBefore: operator,
insertSiblingAfter: operator,
insertBefore: operator,
insertAfter: operator,
replaceNode: operator,
replaceChild: operator,
removeNode: operator,
empty: operator,
removeChild: operator,
get: getter_first_all,
set: operator,
getAttr: getter_first_all,
setAttr: operator,
removeAttr: operator,
getValue: getter_first_all,
setValue: operator,
getHtml: getter_first_all,
setHtml: operator,
encodeURIForm: getter_first,
isFormChanged: getter_first,
cloneNode: queryer,
getStyle: getter_first_all,
getCurrentStyle: getter_first_all,
setStyle: operator,
borderWidth: getter_first,
paddingWidth: getter_first,
marginWidth: getter_first,

//TargetH系列
//……
//JssTargetH系列
getOwnJss: getter_first_all,
getJss: getter_first_all,
setJss: operator,
removeJss: operator,

//ArrayH系列
forEach: operator
},
gsetterMethods: {
//在此json里的方法,会是一个getter与setter的混合体
val: ['getValue', 'setValue'],
html: [
'getHtml', 'setHtml'],
attr: [
'', 'getAttr', 'setAttr'],
css: [
'', 'getCurrentStyle', 'setStyle'],
size: [
'getSize', 'setInnerSize'],
xy: [
'getXY', 'setXY']
}
};

}());


其中wrapMethods的配置规则为:
    //queryer “返回值”的包装结果
    //operator 如果是静态方法,返回第一个参数的包装,如果是原型方法,返回本身
    //getter_all 如果是array,则每一个执行,并返回
    //getter_first 如果是array,则返回第一个执行的返回值
    //getter_first_all 同getter,产出两个方法,一个是getterFirst,一个是getterAll
除了getter_all在实际中没用到外,其它几个都有用到。
上面的例如中,如果把getValue配置成getter_all,那么,W('input').getValue()将会返回所有input元素的值组成的数组。这个结果与YUI3中的NodeList的结果一致,与jquery的结果不一致。
实际上,getValue配置的是get_first_all,所以,它会产出两个方法,即:
W('input').getValue()//返回第一个input的value值
W('input').getValueAll()//返回所有input元素的值组成的数组
前者与jquery一致,后者与YUI3的NodeList一致。
我们并没有改变NodeH的代码,而只是改变NodeC配置,就同时满足了jquery追求与yui3追求。
这也正是qwrap的retouch机制的灵活性的体现:一份严谨生硬的工具集,经retouch,产出个性易用有灵性的产品。

dom_retouch.js中除了为NodeW装甲之外,也产出一个新的QW.Dom的命名空间来,它把DomU、NodeH、EventTargetH、JssTargetH的静态方法集中到一起,这个与YUI2的Dom很相似,就是一个与Dom有关的静态方法集,可以满足YUI2习惯的用户。

另外,还有dom_retouch.js中还有两段略有争议,近期会作出调整,可以忽略。


附: QWrap网址:http://www.qwrap.com

posted on 2011-04-10 12:23  JKisJK  阅读(1583)  评论(1编辑  收藏  举报

导航