您的位置:首页 > Web前端 > JQuery

JQuery 支持 hide 和 show 事件的方法与分析

2014-05-25 22:57 330 查看

问题提出

 JQuery不支持hide和show作为事件形式出现,实际上这两个仅仅是JQuery对象的一个方法(fn);

有一类UI交互需求,根据一个DOM对象的或者显示对附属的DOM对象做相同操作,

一般情况下,利用jqueryhide和show方法的扩展参数中的回调函数,是可以实现的,例如:

$("#book").hide("slow",function(){
$("#booklet").hide()
});


  如果附属DOM是一个动态生成的插件,则在主DOM的hide中处理附DOM的隐藏,就破坏了动态生成插件的灵活性,

因为需要让使用对象(主DOM)自行添加同步显示和隐藏代码。例如每一篇随笔的TAG可以自己输入,

也可以从历史记录中选择,这个选择插件就属于动态生成的,如果在某种交互条件下,需要隐藏掉TAG,

须要使用hide的回调函数处理。

解决方法

  如果jq支持hide和show可以设置事件,并且在hide()和show()调用的时候被触发,

类似一般的click事件绑定和触发,则可以解决此问题(插件来设置其目标DOM的hide和show事件,

完成自身的显示隐藏,而不是目标在hide方法中完成,这样只需要在插件的HTML中设置目标ID即可)。

  但是在jq官网上没有找到hide作为事件,实施上确实没有,

应该是这个不是常规事件,不是由用户能够触发的,故没有涉及为事件,可以理解为动作。

  在网上找到前辈的足迹,并且找到解决方案。
http://stackoverflow.com/questions/2857900/onhide-type-event-in-jqueryhttp://jsfiddle.net/mofle/eZ4X3/
  查看jsfiddle有例子,只需要扩展一下JQ框架

(function($){
$.each(['show','hide'],function(i,val){
var_org=$.fn[val];
$.fn[val]=function(){
this.trigger(val);
return_org.apply(this,arguments);
};
});
})(jQuery);


方法分析

  上面的方法是对JQ框架实现hide和show方法的扩展,我们来看下JQ是怎么实现这两个方法的:

jQuery.each(["toggle","show","hide"],function(i,name){
varcssFn=jQuery.fn[name];
jQuery.fn[name]=function(speed,easing,callback){
returnspeed==null||typeofspeed==="boolean"?
cssFn.apply(this,arguments):
this.animate(genFx(name,true),speed,easing,callback);
};
});


  看样是都是跟fn有关,上面提供的解决方案相当于对JQfn的做了继承,

除了保证原有fn内容(函数)执行(return_org.apply(this,arguments);),

还增加了对hide和show事件的触发(this.trigger(val);)。

fn与$()获得的对象

  那么,fn到底是什么东西?跟$()获得的JQ对象有什么关系?

还是要从刀勒符说起,首先$==JQuery的,然后$就是一个函数,函数内容如下:

//DefinealocalcopyofjQuery
jQuery=function(selector,context){
//ThejQueryobjectisactuallyjusttheinitconstructor'enhanced'
//NeedinitifjQueryiscalled(justallowerrortobethrownifnotincluded)
returnnewjQuery.fn.init(selector,context);
},


  这样使用$符号获取的JQuery对象,实际就是构造函数jQuery.fn.initnew出来的对象,

jQuery.fn.init此函数定义如下,其中this表示new出来的对象,可以看出为array形式的对象,
然后,init==jQuery.fn.init,newjQuery.fn.init==newinit,
故$()对象继承了init.prototype,即我们刚开始关注的jQuery.fn,这样,fn中任何函数,
对于$()对象都可以直接调用即$().hide();


init=jQuery.fn.init=function(selector,context){
......

returnjQuery.makeArray(selector,this);
};

//GivetheinitfunctionthejQueryprototypeforlaterinstantiation
init.prototype=jQuery.fn;



事件与trigger

  那么为什么bind("hide",function(e){})的事件hide,可以被this.trigger("hide");触发调用,

这其中又有哪些道道?

  bind间接调用on,on与bind一样同为jQuery.fn的一个函数,可以被$()对象调用,

on调用实际上执行,是对$()对象数组中的每一个DOM元素调用了jQuery.event.add

bind:function(types,data,fn){
returnthis.on(types,null,data,fn);
},


jQuery.fn.extend({

on:function(types,selector,data,fn,/*INTERNAL*/one){
.......
returnthis.each(function(){
jQuery.event.add(this,types,fn,data,selector);
});
},


  从下面的代码轨迹,看出bind将新的事件对象(handleObj)存入了DOM对象(elem)的events[type]

jQuery._data(elem).events[type]


jQuery.event={

global:{},

add:function(elem,types,handler,data,selector){
vartmp,events,t,handleObjIn,
special,eventHandle,handleObj,
handlers,type,namespaces,origType,
elemData=jQuery._data(elem);
......

//Inittheelement'seventstructureandmainhandler,ifthisisthefirst
if(!(events=elemData.events)){
events=elemData.events={};
}
.......
//Inittheeventhandlerqueueifwe'rethefirst
if(!(handlers=events[type])){
handlers=events[type]=[];
handlers.delegateCount=0;
........
}

.......

//Addtotheelement'shandlerlist,delegatesinfront
if(selector){
handlers.splice(handlers.delegateCount++,0,handleObj);
}else{
handlers.push(handleObj);
}
.......


  同样triggerfn也是从jQuery._data(elem).events[type]获取当前事件的处理函数handle,然后handle在当前对象上执行。

trigger:function(event,data,elem,onlyHandlers){
varhandle,ontype,cur,
bubbleType,special,tmp,i,
eventPath=[elem||document],
type=hasOwn.call(event,"type")?event.type:event,
namespaces=hasOwn.call(event,"namespace")?event.namespace.split("."):[];

cur=tmp=elem=elem||document;
........
//jQueryhandler
handle=(jQuery._data(cur,"events")||{})[event.type]&&jQuery._data(cur,"handle");
if(handle){
handle.apply(cur,data);
}
.........


问题解决代码

  阴影部分为“插件"代码,可以单独裁减掉,而不修改firstdiv控件原有代码。

<html>
<head>
<title>Example</title>
<scripttype="text/javascript"src="./jquery.js"></script>
</head>
<body>

<divid="first"style="width:100px;height:100px;background:green">first</div>
<divid="second"style="width:100px;height:100px;background:yellow"targetDOMID="first">second</div>

<inputtype="button"value="showfirst"id="showFirst"/>
<inputtype="button"value="hidefirst"id="hideFirst"/>

<scripttype="text/javascript">
(function($){ $.each(['show','hide'],function(i,val){ var_org=$.fn[val]; $.fn[val]=function(){ this.trigger(val); return_org.apply(this,arguments); }; }); })(jQuery);

/*插件DOM,给目标DOM(第一个div)添加隐藏/显示事件,
事件触发后,第二个div也隐藏/显示*/
vartargetDOMID=$("#second").attr("targetDOMID");
vartargetDOM=$("#"+targetDOMID);
targetDOM.bind("hide",function(){
$("#second").hide();
})
.bind("show",function(){
$("#second").show();
});

/*按钮click事件触发第一块div的显示和隐藏fn*/
$("#showFirst").click(function(){
$("#first").show();
})
$("#hideFirst").click(function(){
$("#first").hide();
})

</script>

</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: