一直认为js插件是块很难啃的骨头,直到最近,公司封闭即将结束,抽了一些时间好好学习一下jQuery的插件编程基础,总结一下内容。
一、本着快速上手的态度,从公司使用的框架入手,公司前端有自己的一套框架,其中使用了腾讯的artTemplate作为模板渲染页面,可以通过类似el表达式或者jsp的写法渲染前端Html代码,前者通过类似{{each list as value i}}{{/each}}后者通过类似<%for(i=0;i<list.size;i++)%>进行遍历,宗旨都是通过js对象自动填充至html代码内,并根据逻辑进行判断或者循环。
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>xgn插件DEMO</title> <link rel="stylesheet" href="css/zTreeStyle/zTreeStyle.css" type="text/css"> <script src="jquery-1.10.2.min.js"></script> <script src="jquery.ztree.all-3.5.min.js"></script> <script src="template.js"></script> <script> var myTemplateSource = '<h1>{{showTitle}}</h1><div id="container"><input type="text" id="inputText"/><input type="button" id="testBtn" value="测试"/>\ <div id="{{id}}_treeDiv" class="ztree" style="BORDER: silver 1px solid;height:160px;width:140px;display:none"></div>\ </div>'; ;(function($,window,document,undefined){ var setting={ test:"haha", callback:{ beforeDestroy:function(){ alert("DefaultFunction:before destroy"); } } } var methods = { init:function(options){ setting = $.extend(true,{},setting,options); var $this = $(this); $this.data("setting",setting); //渲染树 var render = template.compile(myTemplateSource); var html = render(setting); $("#"+setting.renderId).append(html); var $inputText = $("#inputText"); var $treeDiv = $("#"+setting.id+"_treeDiv"); var $testBtn = $("#testBtn"); var ztreeSetting = { treeId:setting.id, data:{ simpleData:{ enable:true, idKey:"id", pIdKey:"pId" } }, callback:{ onClick:function(event, treeId, treeNode){ $("#inputText").val(treeNode.name); $("#inputText").data("custom_val",treeNode.id); $("#"+setting.id+"_treeDiv").hide(); } } }; $.fn.zTree.init($treeDiv,ztreeSetting,setting.list); $("#inputText").on('focus',function(){$treeDiv.show();}); if($.isFunction(setting.callback.buttonClick)){ $testBtn.on("click",setting.callback.buttonClick); }else{ $testBtn.on("click",function(){alert("所选值为:"+$("#inputText").data("custom_val"))}); } }, destroy:function(){ if($.isFunction(this.data("setting").callback.beforeDestroy)){ alert("haha"); } }, getValue:function(){ return $("#inputText").data("custom_val"); } }; $.fn.xgnTree = function(methodName){ if(methods[methodName]){ return methods[methodName].apply(this,Array.prototype.slice.call(arguments,1)); }else if(typeof methodName === 'object' || !methodName){ return methods.init.apply(this,arguments); }else{ $.error('方法'+methodName+'不存在!'); } }; })(jQuery,window,document) </script> <script> $(function(){ var setting = { id:"popTree", renderId:"content", showTitle:"jQuery插件下拉树", list: [{id:"sy",pId:"sy",name:"摄影"}, {id:"dy",pId:"dy",name:"电影"}, {id:"my",pId:"my",name:"民谣"}, {id:"lx",pId:"lx",name:"旅行"}, {id:"jt",pId:"jt",name:"吉他"}], callback:{ buttonClick:function(event){ $("#content").xgnTree("destroy"); } } }; $("#content").xgnTree(setting); }); </script> </head> <body> <div id="content"></div> </body> </html>
二、jQuery插件结构:看了一本《jQuery高级编程》的书,总结目前有3种方式进行插件的开发,(1)类级别插件开发,使用$.extend对jQuery全局对象进行添加类级别方法进行开发(2)对象级别插件开发,使用$.fn.pluginName进行开发,通过对jQuery对象进行开发;(3)使用widgetFactory插件开发,还不太了解,应该有一套相应的技术规范。主要使用第二种进行插件开发;
整个插件的架构像上面的代码一样,最外层通过一个自调用方法,传入jQuery,window,document对象,确保方法内部可以获得正确的环境变量;
$.fn.xgnTree = function(methodName){ if(methods[methodName]){ return methods[methodName].apply(this,Array.prototype.slice.call(arguments,1)); }else if(typeof methodName === 'object' || !methodName){ return methods.init.apply(this,arguments); }else{ $.error('方法'+methodName+'不存在!'); } };
当传入一个字符串且有该名称的方法时,调用相应的方法,如$("#content").xgnTree("destroy"),类似jqueryUi的用法;传入一个obj或者空时,调用init初始化方法;传入的字符串没有这个方法时报错。
三、setting的存储还是要提一下,困惑了一下午,公司的前端并没有采取这种对象字面量的形式,而是直接在方法里,使用this.setting={}的形式使用,而在这个代码里是使用的一个私有变量,当时不清楚到底应不应该使用$.data方法将setting信息保存下来,但是又不知道其他的什么好方法,看了别人的文章,发现就是通过$(this).data()进行存储的,在别的方法里再通过data将setting取出。
效果图: