首页 > 代码库 > 下拉框插件开发 (二)
下拉框插件开发 (二)
今天有事出去了一趟,晚上加了下夜班,终于将它完成了,后续有bug,欢迎探讨。
附上:github地址 https://github.com/mapletao/downdrop
1,需求更新,完成自己想到的
对js里面的需求及每个方法要做的内容简述的描述了下并将其实现。
2.js编写
1.立即执行函数,构造一个Downdrop函数,并注册该函数,同时进行安全处理,前面的;是为了执行出错的问题
;(function(){ var Downdrop=function(opt){ if(!(this instanceof Downdrop)){ return new Downdrop(opt); } this.init(opt); }; window.Downdrop=Downdrop; })();
2.初始化函数
初始化函数主要是做5件事
1:扩展默认配置 setOpt
2: 处理默认配置 dealOpt
3: 插入下拉框组件 setHtml
4: 设置事件 setFun
5: 解除配置信息 removeOpt
3:扩展默认配置
对参数进行处理,并扩展,设置默认参数
setOpt:function(opt){ this.ulTemp=[‘<div class="downdrop">‘, ‘<div class="downdrop-header">请选择</div>‘, ‘<i class="angle"></i>‘, ‘<ul class="downdrop-con">‘, ‘</ul>‘, ‘</div>‘].join(‘‘); this.setting = { liTemp:‘<li data-val="{{val}}">{{text}}</li>‘, text:true, isHide:true, }; mapletao.extend(this.setting,opt); },
4:处理默认配置
处理列表项点击时该执行的事件,并将其保存在数组中,减少后面点击时的多重判断
dealOpt:function(){ var self=this; self.dealLiFns=[]; if(self.setting.text){ self.dealLiFns.push(function(self){ self.headerDom.innerHTML = this.innerHTML; self.headerDom.setAttribute("data-val",this.getAttribute("data-val")); }); } if(self.setting.isHide){ self.dealLiFns.push(function(self){ self.conDom.style.display = "none"; }); } if(self.setting.cb){ self.dealLiFns.push(cb); } },
5:插入下拉框组件
将下拉框html结构,并处理数据,并将数据插入到列表容器中,并保存将要用到的元素,后面就不需再去页面找了
setHtml:function(){ var self = this; self.setting.ele.innerHTML=self.ulTemp; self.setEle(); self.setList(self.setting.data); }, setList:function(data){ var self=this; self.lis=‘‘; data.forEach(function(obj){ self.lis += self.formateString(self.setting.liTemp,obj); }); self.conDom.innerHTML = self.lis; this.headerDom.innerHTML = "请选择"; }, formateString:function(str,data){ return str.replace(/\{\{(\w+)\}\}/g,function(match,key){ return typeof data[key] === undefined? ‘‘ : data[key]; }); }, setEle:function(){ var ele=this.setting.ele; this.headerDom=ele.getElementsByClassName("downdrop-header")[0]; this.conDoms=document.getElementsByClassName("downdrop-con"); this.conDom=ele.getElementsByClassName("downdrop-con")[0]; },
6:事件设置
主要对4个元素进行设置
1:ele 下拉框插件容器 setEleClick 阻止冒泡,下拉框元素里面发生的事件不被外界获取,外界操作不影响里面的操作。
2:下拉框头部 setHeaderClick 头部点击让列表显示,并将其它的隐藏
3: 下拉列表容器 setConClick 代理模式,对下拉列表容器绑定点击事件,当列表项内容重新加载时正常使用,捕获li点击事件并处理
4: document setDocClick 当点击其它地方时让所有下拉框列表内容的隐藏
setFun:function(){ this.setEleClick(); this.setHeaderClick(); this.setConClick(); this.setDocClick(); }, setEleClick:function(){ var self=this; eventUtil.bindEvent(this.setting.ele,"click",self.setDomBubble); }, setDomBubble:function(e){ eventUtil.stopPropagation(e); }, setHeaderClick:function(){ var self=this; self.dealHeaderFn=self.bindFn(self.dealHeaderFn,self); eventUtil.bindEvent(this.headerDom,"click",self.dealHeaderFn); }, dealHeaderFn:function(e,self){ self.hideDom(e,self); self.conDom.style.display = "block"; }, setConClick:function(){ var self=this; self.dealLiFn=self.bindFn(self.dealLiFn,self); eventUtil.bindEvent(this.conDom,"click",self.dealLiFn); }, dealLiFn:function(e,self){ e = eventUtil.getEvent(e); var target = eventUtil.getEventSrc(e); if(target.tagName.toLowerCase() === "li"){ self.dealLiFns.forEach(function(obj){ obj.call(target,self); }); target=null; } }, bindFn:function(fn,args){ return function(e){ fn.call(this,e,args); }; }, hideDom:function(e,self){ for(var i=0;i<self.conDoms.length;i++){ self.conDoms[i].style.display = "none"; } }, setDocClick:function(){ var self = this; Downdrop.prototype.hideDom=self.bindFn(self.hideDom,self); eventUtil.bindEvent(document,"click",self.hideDom); },
7:解除配置信息
删除一些以后不会用到的属性
removeOpt:function(){ delete this.setting; delete this.lis; delete this.ulTemp; }
8:测试
单元测试,改变参数,看看执行结果
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>下拉框</title> <link rel="stylesheet" type="text/css" href="css/reset.css" /> <link rel="stylesheet" type="text/css" href="css/downdrop.css" /> </head> <body> <p>默认</p> <div style="width:200px;margin-left: 20px;margin-top:10px;" id="J_test1"> </div> <p>不赋值</p> <div style="width:200px;margin-left: 20px;margin-top:10px;" id="J_test2"> </div> <p>不隐藏</p> <div style="width:200px;margin-left: 20px;margin-top:10px;" id="J_test3"> </div> <p>不赋值,不隐藏</p> <div style="width:200px;margin-left: 20px;margin-top:10px;" id="J_test4"> </div> <script src="js/common.js"></script> <script src="js/downdrop.js"></script> <script type="text/javascript"> var data=[{ "val":1, "text":"语文" },{ "val":2, "text":"数学" },{ "val":3, "text":"英语" },{ "val":4, "text":"历史" },{ "val":5, "text":"化学" },{ "val":6, "text":"生物" },{ "val":7, "text":"物理" }]; var test1={ ele:document.getElementById("J_test1"), data:data }; var obj=new Downdrop(test1); var test2={ ele:document.getElementById("J_test2"), data:data, text:false } var obj2=Downdrop(test2); var test3={ ele:document.getElementById("J_test3"), data:data, isHide:false } var obj3=new Downdrop(test3); var test4={ ele:document.getElementById("J_test4"), data:data, isHide:false, text:false }; var obj4=new Downdrop(test4); </script> </body> </html>
9:测试结果
完成!
10:结语:
首先说说在这个组件开发中遇到的坑,参数传递,事件绑定中,作用域指向会偏离,指向当前点击的事件源,可能不是你自己想要的,这里用了下参与者模式,将我需要的用参数的形式传递,还用到了call,将this指向改成我想要的。还有对事件的封装,增强了自己的代码逻辑能力。有不足的地方,还请多多见谅。后面也会不时的进行bug处理,以及优化及扩张。
下拉框插件开发 (二)