jquery技巧之让任何组件都支持类似dom的事件管理_jquery

jquery技巧之让任何组件都支持类似dom的事件管理_jquery

ID:30780691

大小:182.72 KB

页数:15页

时间:2019-01-03

上传者:U-991
jquery技巧之让任何组件都支持类似dom的事件管理_jquery_第1页
jquery技巧之让任何组件都支持类似dom的事件管理_jquery_第2页
jquery技巧之让任何组件都支持类似dom的事件管理_jquery_第3页
jquery技巧之让任何组件都支持类似dom的事件管理_jquery_第4页
jquery技巧之让任何组件都支持类似dom的事件管理_jquery_第5页
资源描述:

《jquery技巧之让任何组件都支持类似dom的事件管理_jquery》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

jQuery技巧之让任何组件都支持类似DOM的事件管理本文介绍一个jquery的小技巧,能让任意组件对象都能支持类似DOM的事件管理,也就是说除了派发事件,添加或删除事件监听器,述能支持事件冒泡,阻止事件默认行为等等。在jquery的帮助下,使用这个方法来管理普通对象的事件就跟管理DOM对象的事件一模一样,虽然在最后当你看到这个小技巧的具体内容时,你可能会觉得原来如此或者不过如此,但是我觉得如果能把普通的发布-订阅模式的实现改成DOM类似的事件机制,那开发出來的组件一定会有更大的灵活性和扩展性,而且我也是第一次使用这种方法(见识太浅的原因),觉得它的使用价值还蛮大的,所以就把它分享岀来了。在正式介绍这个技巧之前,得先说一下我之前考虑的一种方法,也就是发布-订阅模式,看看它能解决什么问题以及它存在的问题。1.发布-订阅模式很多博客包括书本上都说javascript要实现组件的自定义事件的话,可以采用发布-订阅模式,起初我也是坚定不移地这么认为的,于是用jquery的$.Callbacks写了一个:define(function(require,exports,module){var$=requirejquery');varClass=require('・/class');functionisFunc(f){returnObject,prototype.toString.apply(f)二二二'[objectFunction]';}/***这个基类可以让普通的类具备事件驱动的能力*提供类似jq的onofftrigger方法,不考虑one方法,也不考虑命名空间*举例:*vare二newEventBase();*c.on(Jload,,function(){*console・log('loaded');*});*e.trigger(,load,);//loaded*e.off('load');*/varEventBase=Class({instanceMembers:{init:function(){this,events二{};//把$・Callbacks的flag设置成一个实例屈性,以便子类可以覆盖this.CALLBACKS_FLAG='unique';}, on:function(type,calIback){type=$・trim(type);//如果type或者callback参数无效则不处理if(!(type&&isFunc(callback)))return;varevent=this・events[type];if(!event){//定义一个新的jq队列,且该队列不能添加重复的回调event=this.events[type]=$.Callbacks(this.CALLBACKS_FLAG);}~//把callback添加到这个队列中,这个队列可以通过type来访问event.add(callback);},off:function(type,callback){type=$.trim(type);if(!type)return;varevent二this.events[type];if(!event)return;if(isFunc(callback)){//如果同时传递type跟callback,则将callback从type对应的队列屮移除event.remove(callback);}else{〃否则就移除整个type对应的队列deletethis.events[type];}},trigger:function(){varargs二[].siice.apply(arguments),type=args[0];//第一个参数转为typetype=$.trim(type);if(!type)return;varevent二this.events[type];if(!event)return;//用剩卜•的参数來触发type对应的回调〃同时把回调的上下文设置成当前实例event.fireWith(this,args,slice(1));}}});returnEventBase;});(基于seajs以及《详解Javascript的继承实现》介绍的继承库class,js)只要任何组件继承这个EventBase,就能继承它提供的onofftrigger方法來完成消息的订阅,发布和取消订阅功能,比如我下面想要实现的这个FileUploadBaseView:definc(fimction(require,exports,module){var$=require(Jjquery');varClass=require('・/class'); varEventBase二require(,./eventBase');varDEFAULTS二{data:[],//要展示的数据列表,列表元素必须是object类型的,如[{url:'XXX・png'},{url:'yyyy.png,}]sizeLimit:0,//用来限制BaseView中的展示的元素个数,为0表示不限制readonly:false,//用来控制BaseView屮的元素是否允许增加和删除onBeforeRender:$.noop,//对应beforeRender事件,在render方法调用前触发onRender:$.noop,//对应render事件,在render方法调用后触发onBeforeAppend:$.noop,//对应beforeAppend事件,在append方法调用前触发onAppend:$.noop,//对应append事件,在append方法调用后触发onBcforcRcmovc:$.noop,//对应bcforcRcmovc事件,在remove方法调用而触发onRemove:$.noop//对应remove事件,在remove方法调用后触发};/***数据解析,给每个元素的添加一个唯一标识_uuid,方便杳找*/functionresolveData(ctx,data){vartime二newDate().getTime();return$.map(data,function(d){d._uuid='_uuid'+time+Math,floor(Math,random()*100000);})?~}varFi1eUploadBaseView二Class({instanceMembers:{init:function(options){this.base();this,options=this.getOptions(options);},getOptions:function(options){return$.extend({},DEFAULTS,options); render:function(){},append:function(data){},remove:function(prop){}},extend:EventBase});returnFileUploadBaseView;});实际调用测试如下:>var$=seajs.require(1jquery*);varFileUploadBaseView=seajs.require(,mod/FileUploadBaseView,);varf=n己wFileUploadBsseView();<•undefinedrTaraetCLass/baseProto:TarcjetCLass.base:undefined,events:Object.CAL.CALLBACKSFLAG:-uniqueMbase:undefined▼baseProto:TargetClass►constructo「:functiocTarcietCLassO►off:function(type,caltback)•on:function(type,callback)rigger:function()proto""jooiect►events:Obiect►ODtions:Obiect►proto:TargetClass>f.name=1jason1;f.on(1hello"function(foo,bar){consoleI测试代码二:define(function(require,exports,module){var$=requireCjquery");varClass二requireCmod/class,);varEventBase=requireCmod/eventBase,);varDemo=window,demo=Class({instanceMembers:{init:function(element,options){this.$element二$(elernent); this.base(this.$clcment);〃添加监听this.onCbeforeRender',$•proxy(options.onBeforeRender,this));this.onCrender5,$.proxy(options.onRender,this));},render:function(){//触发bcforcRcnder事件vare=$.EventCbeforeRender");this,trigger(e);if(e.isDefaultPrevented())return;//主要逻辑代码console.log(,rendercomplete!");//触发render事件this,trigger(5render");}},extend:EventBase});vardemo=newDemo('#demo',{onBeforeRender:function(e){console.log(,beforeRendereventtriggered!;},onRender:function(e){console.logCrendereventtriggered!5);}});demo,on(JbcforcRcndcr,,function(e){e.preventDefault();console.log(5beforeRendereventtriggered2!');});demo,on('beforeRender",function(e){console.log(,bcforcRcndcreventtriggered3!,);});demo,render();});在这个测试了,我定义了一个跟DOM相关的Demo组件并继承了EventBase这个事件管理的类,给bcforcRcnder事件添加了3个监听,其小一个有加prevetDefault()的调用,而且该回调还不是最后一个,最后的测试结果是:beforeRendereventtriggered!beforeRendereventtriggered2!beforeRend已广eventtriggered3!>从结果可以看到render方法的主要逻辑代码跟后面的render事件都没有执行,所有beforcRcnder的监听器都执彳亍了,说明c.prevcntDcfault()生效了,而且它没有对beforeRender的事件队列产生影响。2)模拟跟D0M无关联的普通对象 测试代码一:define(function(require,exports,module){var$=requireCjquery');varClass二requireCmod/class,);varEventBase=require(,mod/eventBase,);varDemo=window.demo=Class({instanccMcmbcrs:{init:function(options){this,base();〃添加监听this.onCbeforeRender',$.proxy(options.onBeforeRender,this));this.on(,tendcr,,$.proxy(options.onRcndcr,this));},render:function(){//触发beforeRender事件vare=$.Event('beforeRender');this.trigger(e);if(e.isDefaultPrevented())return;//主要逻辑代码console.log(,rendercomplete;//触发render事件this,triggerrendcr,);}},extend:EventBase});vardemo=newDemo({onBeforeRender:function(e){console.log(,beforeRendereventtriggered;},});demo,render();});在这个测试里,我定义了一个跟DOM无关的Demo组件并继承了EventBase这个事件管理的类,给bcforcRcndcr事件和render事件都添加了一个监听,render方法中也有打卬信息来模拟真实的逻辑,最后的测试结果是:完全与预期的一致。测试代码二:define(function(require,exports,module){var$=requireCjquery'); varClass二requireCmod/class,);varEventBase=requireCmod/eventBase');varDemo=window.demo=Class({instanceMembcrs:{init:function(options){this,base();〃添加监听this.on(‘beforeRender',$.proxy(options.onBeforeRender,this));this.on(,tendcr,,$.proxy(options.onRcndcr,this));},render:function(){//触发beforeRender事件vare=$.Event('beforeRender');this.trigger(e);if(e.isDefaultPrevented())return;//主要逻辑代码console.log(,rendercomplete;//触发render事件this,triggerrendcr,);}},extend:EventBase});vardemo=newDemo({onBeforeRender:function(e){console.log(,beforeRendereventtriggered;},});demo,on('beforeRender',function(e){e.preventDefault();console.log(,beforeRendcreventtriggcrcd2!,);});demo.onCbeforeRender',function(e){console.log(5beforeRendereventtriggered3!');});demo,render();});在这个测试了,我定义了一个跟DOM无关的Demo组件并继承了EventBase这个事件管理的类,给beforeRender事件添加了3个监听,其中一个有加prevetDeTault()的调用,而冃该回调还不是最后一个,最后的测试结果是:beforeRend亡广eventtriggered!beforeRend亡广eventtriggered2!beforeRende厂eventtriggered3! 从结果可以看到,render方法的主要逻辑代码跟后面的render事件都没有执行,所冇beforeRender的监听器都执彳亍了,说明e.preventDefault()生效了,而且它没有对bcforcRender的事件队列产生影响。所以从2个测试来看,通过改造后的EventBase,我们得到了一个可以让任意对象支持jquery事件管理机制的方法,将來在考虑用事件机制來解耦的时候,就不用再去考虑前面第一个介绍的发布-订阅模式了,而且相对而言这个方法功能更强更稳定,也更符合你平常使用jquery操作D0M的习惯。4.木文小结有2点需要再说明一下的是:1)即使不用jquery按照第1部分最后提出的思路,把第一部分常规的发布-订阅模式改造一下也可以的,只不过用jquery更加简洁些;2)最终用jquery的事件机制來实现任意对象的事件管理,一方面是用到了代理模式,更重要的还是要用发布-订阅模式,只不过最后的这个实现是±jquery帮我们把第一部分的发布-订阅实现改造好了而已。以上内容是针对JQuery技巧之让任何组件都支持类似D0M的事件管理的相关知识,希望对大家有所帮助!

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭