一直以来做开发,尤其是web开发,少不了和JavaScript打交道,自认为js脚本还可以吧!
有一天,我发现 select控件、下拉框、ajax请求、文件上传控件等等
大多地方都要使用的到,
有些虽然用的也是别人的写好的控件,可是根据项目的要求,自己想在封装一下,来满足
自己的需求!
可是写了很久,以失败而告终!常用的,说实话,大家都会,可是要深入研究久逊色点了。
所以,不能放弃治疗,哪里有病就要治疗哪里,绝不能怠慢!
html调用
引入样式:
引入脚本:
控件:
js调用
$("#equ_category_small").selectTree({
url: "/equipment/GetCategoryList",
isRadio: true,
title: "请选择设备",
requestCallBack: function (data) {
var treedata = [];
if (data.code == 0) {
$(data.data.CategoryBig).each(function (i, o) {
var node = {};
var id = o.categoryId;
var pid = o.pCategoryId;
node.id = id;
node.pId = pid;
node.name = o.categoryName;
node.isParent = true;
node.open = true;
treedata.push(node);
});
$(data.data.CategorySmall).each(function (i, o) {
var node = {};
var id = o.categoryId;
var pid = o.pCategoryId;
node.id = id;
node.pId = pid;
node.name = o.categoryName;
treedata.push(node);
});
}
return treedata;
},
selected: function (node) {
$("#equ_category_small").val(node[0].id);
//$("#equ_category_small").valid();
}
});
后台数据
@RequestMapping("GetCategoryList")
@ResponseBody
public String GetCategoryList()
{
List<BasEquType> ListSmall =basEquTypeService.categoryListSmall(0);
List<BasEquType> ListBig = basEquTypeService.categoryListBig(0);
Dictionary<String,List<BasEquType>> map=new Hashtable<>();
map.put("CategoryBig",ListBig);
map.put("CategorySmall",ListSmall);
Result result=new Result();
result.setCode("0");
result.setData(map);
return JSON.toJSONString(result) ;
}
上面只是提供了一个完整示例,并没有介绍如何封装js组件,好了,接下重点讲接一下。
创建匿名函数
Q: 什么是匿名函数?
A: 顾名思义就是没有名称的函数
Q: 匿名函数作用是什么?
A: 匿名函数的作用主要是实现自己定义内部中的函数,从而扩大函数的使用功能
Q: 为什么要使用匿名函数?
A: 因为页面的脚本会越来越多,全局变量和和方法会越来越多,主要是为了避免重名,还有就是模块化。
匿名函数:
匿名函数
(function ($) {
//....封装组件逻辑
})(jQuery);
--------------------------------------------------------------------
拆分来看
var fn = function($){
//.....组件封装逻辑
};
fn(jQuery);
立即执行的函数
创建模块内容
模块就是实现特定功能的一组方法。
a. 一般写法 :只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。
例如:
function fun1(){
//...
}
function fun2(){
//...
}
上面的函数fun1()和fun2(),组成一个模块。使用的时候,直接调用就行了。
b. 为了解决上面的缺点,可以把模块写成一个对象,所有的模块成员都放到这个对象里面
var module1 = new Object({
_count : 0,
fun1: function (){
//...
},
fun2: function (){
//...
}
});
上面的函数fun1()和fun2(),都封装在module1对象里。使用的时候,就是调用这个对象的属性。
module1.fun1();
但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。
module1._count = 100;
c. 为了解决这个问题,我们使用”立即执行函数”(Immediately-Invoked Function Expression,IIFE)也就是匿名函数,可以达到不暴露私有成员的目的。
var module1 = (function(){
var _count = 0;
var fun1= function(){
//...
};
var fun2= function(){
//...
};
return {
fun1: fun1,
fun2: fun2
};
})();
使用上面的写法,外部代码无法读取内部的_count变量。
console.info(module1._count); //undefined
d.一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用”放大模式”(augmentation)。
var module1 = (function (mod){
mod.fun3= function () {
//...
};
return mod;
})(module1);
上面的代码为module1模块添加了一个新方法fun3(),然后返回新的module1模块。
e.在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上一节的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用”宽放大模式”。(Loose augmentation)。
var module1 = ( function (mod){
//...
return mod;
})(window.module1 || {});
模块的写法就介绍到这里了,在我们创建的匿名函数里面写我们需要的函数和属性,如上图封装代码缩略图所示
JQuery 的扩展方法$.extend()的用法和含义:
extend()方法作用就是合并另个对象,有相同的则覆盖,没有相同的则添加
例子1:
var settings = { url: '#', title: 'xxx', param: "ok" };
var options = { title: 'abc', param: "no" };
$.extend(settings, options);
结果1:
settings == { url: '#', title: 'abc', param: "no" }
例子2:
var empty = {};
var defaults = { url: '#', title: 'xxx', param: "ok" };
var options = { title: 'abc', param: "no" };
var settings = $.extend(empty, defaults, options);
结果:
settings == { url: '#', title: 'abc', param: "no" }
empty == { url: '#', title: 'abc', param: "no" }
prototype 属性的用法和含义:
prototype 属性使您有能力向对象添加属性和方法
例如:
SelectTree.prototype.initDom = function ()
SelectTree.prototype.setCheckNode = function ()
.......................................
$.fn.selectTree = function (options) {//…}
这个就表示向jquery对象添加自定义方法
$.fn.selectTree = function (options, param) {
//...
};
调用:
$("#equ_category_small").selectTree({
//...
});
脚本 selecttree.js
(function ($) { "use strict"; var CON_TYPE_NULL = "请选择"; var BASEHtml = "
"; var TreeIndex = 1; /** * selectTree插件基于jquery,bootstrap,ztree,使用时要引用相应的js * param: { * NullText:默认提示信息 * objTitle: "btnTitle", 选择后需要显示的控件I * isRadio: false, 是否是单选 * url: "/Machine/KBS/GetContentTypes" 数据请求的URL 暂时基于post方式请求 * requestCallBack:数据获取后的回调方法 * succes:点击确定按钮的处理事件 * cancel:点击取消按钮的处理事件 * selected:单选选定回调 * isParentSelect:父级可选 * }, * 使用:$("#type").selectTree(); */ function SelectTree(obj, params) { this.tiggerObj = obj; this.param = this.param || {}; if (!this.param.NullText || this.param.NullText == "") { this.param.NullText = CON_TYPE_NULL; } this.param = $.extend(this.param, params); this.initDom(); this.objTitle = $(this.tiggerObj).prev().children("button").children("span").eq(0); this.ishide = true; this.isCancel = true; if (this.param.title) { this.objTitle.text(this.param.title); } this.getContent(); this.initValue(); this.initEvent(); } SelectTree.prototype.reload = function (params) { this.param = $.extend(this.param, params); //this.objTitle = $(this.tiggerObj).prev().children("button").children("span").eq(0); this.ishide = true; this.isCancel = true; if (this.param.title) { this.objTitle.text(this.param.title); } this.getContent(); this.initValue(); this.initEvent(); }; //初始化组件DOM元素 SelectTree.prototype.initDom = function () { this.tiggerObj.css({ "height": "0.5px", "width": "0px", "padding": "0px", "margin": "0px" }); this.tiggerObj.before(BASEHtml); if (this.param.isRadio) { $(".selecttree .panel-footer .btn").hide(); } }; //初始化事件定义 SelectTree.prototype.initEvent = function () { var self = this; var isthis = false; //点击组件内部触发动作 $(".dropdown .panel-body").click(function () { self.ishide = false; if (self.param.isRadio) { self.isCancel = false; } }); if (!self.param.isRadio) { var btnCancel = $(this.tiggerObj).parent().find("#btnCancel"); $(btnCancel).click(function () { //console.log("btnCancel"); self.ishide = true; if (self.param.cancel) { self.param.cancel(); } }); var btnOk = $(this.tiggerObj).parent().find("#btnOK"); $(btnOk).click(function () { // console.log("btnOk"); self.ishide = true; self.isCancel = false; if (self.param.succes) { self.param.succes(); } }); } //组件消失时触发 $(this.tiggerObj).parent().on("hide.bs.dropdown", function (e) { var node = self.TreeObj.getSelectedNodes()[0]; if (self.param.isRadio && self.param.isParentSelect) { var selectedNodes = self.TreeObj.getSelectedNodes(); if (self.param.selected) { self.param.selected(selectedNodes); } var names = []; var id = []; var tid = []; var pname = ""; var pid = ""; $(selectedNodes).each(function (i, o) { names.push(o.name); id.push(o.id); tid.push(o.tId); var pnode = o.getParentNode(); if (pnode && pnode != null) { pname += pnode.name; if (pnode.value) { pid += pnode.value; } else { pid += pnode.id; } } }); var name = names.join(","); if (name == "") name = self.param.NullText; $(self.objTitle).text(name); if (self.param.name) { $("#" + self.param.name).val(name); } if (self.param.parentName) { $("#" + self.param.parentName).val(pname); } if (self.param.parentValue) { $("#" + self.param.parentValue).val(pid); } $(self.tiggerObj).val(id.join(",")); $(self.tiggerObj).data("tids", tid.join(",")); return; } if ((!self.ishide && !self.param.isRadio) || (self.param.isRadio && !self.ishide && node && node.isParent)) { self.ishide = true; if (self.param.isRadio) { self.isCancel = true; } e.preventDefault(); } else { if (!self.isCancel) { var treeObj = self.TreeObj; var selectedNodes; if (self.param.isRadio) { selectedNodes = treeObj.getSelectedNodes(); } else { selectedNodes = treeObj.getCheckedNodes(true); } if (self.param.selected) { self.param.selected(selectedNodes); } var names = []; var id = []; var tid = []; var pname = ""; var pid = ""; $(selectedNodes).each(function (i, o) { if (!o.isParent) { names.push(o.name); id.push(o.id); tid.push(o.tId); var pnode = o.getParentNode(); if (pnode && pnode != null) { pname += pnode.name; if (pnode.value) { pid += pnode.value; } else { pid += pnode.id; } } } }); var name = names.join(","); if (name == "") name = self.param.NullText; $(self.objTitle).text(name); if (self.param.name) { $("#" + self.param.name).val(name); } if (self.param.parentName) { $("#" + self.param.parentName).val(pname); } if (self.param.parentValue) { $("#" + self.param.parentValue).val(pid); } $(self.tiggerObj).val(id.join(",")); $(self.tiggerObj).data("tids", tid.join(",")); } } }); //组件显示时触发 $(this.tiggerObj).parent().on("show.bs.dropdown", function (e) { // console.log($(self.tiggerObj).data("tids")); self.setCheckNode(); self.isCancel = true; }); }; //设置选择node SelectTree.prototype.setCheckNode = function () { var self = this; if (self.param.isRadio) { var selectnode = self.TreeObj.getSelectedNodes(); if (selectnode.length > 0) { self.TreeObj.cancelSelectedNode(selectnode[0]); } } else { self.TreeObj.checkAllNodes(false); } var check = $(self.tiggerObj).data("tids"); if (check) { var tids = check.split(","); $(tids).each(function (i, o) { var node = self.TreeObj.getNodeByTId(o); if (self.param.isRadio) { self.TreeObj.selectNode(node); } else { self.TreeObj.checkNode(node, true, true); } }); } }; //获取树内容 SelectTree.prototype.getContent = function () { var url = this.param.url; var self = this; $.ajax({ "type": "Get", //"contentType": "application/json", "url": url, "async": false, //"dataType": "json", "success": function (resp) { var zNodes = []; var setting = treeSetting(self.param.isRadio); if (self.param.requestCallBack) { zNodes = self.param.requestCallBack($.parseJSON(resp)); } else { zNodes = $.parseJSON(resp).data; } var treeContent = $(self.tiggerObj).prev().children().children(".panel-body").children(".ztree").eq(0); $(treeContent)[0].id = "tree" + TreeIndex; self.TreeObj = $.fn.zTree.init(treeContent, setting, zNodes); TreeIndex++; // self.initValue(); } }); }; //初始化组件值 SelectTree.prototype.initValue = function () { var value = $(this.tiggerObj).val(); var self = this; if (value && value != "") { var ids = value.split(','); //var nodes = []; var tids = []; var name = []; $(ids).each(function (i, o) { var node = self.TreeObj.getNodesByParam("id", o, null)[0]; if (node && node != null) { //nodes.push(node); name.push(node.name); tids.push(node.tId); } }); if (tids.length > 0) { this.objTitle.text(name.join(',')); $(this.tiggerObj).data("tids", tids.join(',')) } } else { this.objTitle.text(this.param.NullText); } }; //获取ztree设置 function treeSetting(isradio) { if (isradio) { return { data: { simpleData: { enable: true } } }; } else { return { check: { enable: true, nocheckInherit: false }, data: { simpleData: { enable: true } } }; } } $.fn.selectTree = function (options) { var select = new SelectTree(this, options); return select; }; })(jQuery);
样式 selecttree.css
.input-group .dropdown { display: table-cell; }
.selecttree { padding-left: 0; padding-right: 0; border: solid 1px #ccc; }
.ztree * { font-size:1em; }
.dropdown { display: inline-block; }
.atct .dropdown { max-width: 530px; }
.atct .dropdown button:first-child { overflow: hidden; text-overflow: ellipsis; -o-text-overflow: ellipsis; white-space: nowrap; width: 490px; display: block; }
.dropdown-menu { padding: 0; }
.panel-footer { width: 100%; padding: 0; }
.selecttree ul.ztree { max-height: 200px; overflow-y: auto; overflow-x: auto; }
.btn { border: 1px solid #e6e6e6; }