最近一直用layui进行页面的重构,这个框架十分适合我们后台人员开发。简单易用,但是layui本身不支持双向绑定,所以很多情况下,我们在支持动态的控件加载时,需要反复刷新。这里我自己封装了一个common模块。话不多说,直接上代码。

  1.  

//Author :chenzihao
//Date :2018/8/27
//Discrption:自定义公共方法(持续扩充ing)
layui.define(['layer', 'form', 'table', 'jquery'], function (exports) {

  1.  

//内置laydui对象
var $ = layui.$;
var layer = layui.layer;
var form = layui.form;
var table = layui.table;

  1.  

var extend = {

  1.  

select: function (obj) {
var url = obj.url,//请求数据源的url
data = obj.requestdata,//请求参数
type = obj.type ? obj.type : 'get',//请求方法
elemIds = obj.elemIds,//select元素集合(可以是单个字符串,或Array)
dataText = obj.dataText,//select选项的文本字段名
dataValue = obj.dataValue,//select选项的value字段名
otherOption = obj.otherOption,//其他选项
defaultValue = obj.defaultValue,//默认选项值
func = obj.selectFunc,//下拉框选项监听事件
isAll = obj.isAll,//是否所有select绑定相同监听事件
done = obj.done,//渲染完成执行事件
selectFilter = obj.selectFilter ? obj.selectFilter : obj.elemIds,//自定义的select filter,默认与elemIds同名 (可以是单个字符串,或Array)
isLocalRender = obj.isLocalRender ? obj.isLocalRender : false,//是否开启局部刷新 默认不开启
message = obj.errorMessage ? obj.message : "网络异常",//请求异常的message
response = obj.response ? obj.response : {
statusName: 'code',
statusCode: 'success',
dataName: 'data',
msgName: 'message'
};//返回参数名配置

  1.  

$.ajax({
url: url,
data: data,
type: type,
dataType: "JSON",
error: function (error) {
console.log("异常" + error);
layer.msg(message);
},
success: function (res) {
var result;
if (typeof (res) == 'string') {
result = JSON.parse(res);
}
else {
result = res;
}

  1.  

if (result[response.statusName] != response.statusCode) {
layer.alert(result[response.msgName]);
}

  1.  

var options;
if (result[response.dataName]) {
options = result[response.dataName];
}
else {
options = result.Data;
}
var template="";

  1.  

//加载select的option集合
if (otherOption) {
template = otherOption;
}

  1.  

for (var index in options) {
if (defaultValue && (options[index][dataValue] == defaultValue || options[index][dataText] == defaultValue)) {
template += "<option selected value='" + options[index][dataValue] + "'>" + options[index][dataText] + "</option>";
}
else {
template += "<option value='" + options[index][dataValue] + "'>" + options[index][dataText] + "</option>";
}
}

  1.  

if (typeof (elemIds) == 'string') {
$("#" + elemIds).html(template);
}
else if (elemIds instanceof Array) {
for (var index in elemIds) {
$("#" + elemIds[index]).html(template);
}
}

  1.  

//是否局部渲染
if (isLocalRender) {

  1.  

if (typeof (selectFilter) == 'string') {
form.render('select', selectFilter);
}
else if (selectFilter instanceof Array) {
for (var index in selectFilter) {
form.render('select', selectFilter[index]);
}
}
}
else {
form.render('select');
}

  1.  

//渲染完成事件
if (done) {
done();
}

  1.  

//监听select下拉选项事件
if (func) {

  1.  

//多绑定事件
if (func instanceof Array) {
for (var index in func) {
//select同一个监听事件(一个select,多个func,只绑定第一个func)
if (typeof (selectFilter) == 'string') {
form.on("select(" + selectFilter + ")", func[index]);
break;
}
//select不同的监听 一 一对应
else if (selectFilter instanceof Array) {
form.on("select(" + selectFilter[index] + ")", func[index]);
}
}
}
//单绑定事件
else {
if (typeof (selectFilter) == 'string') {
form.on("select(" + selectFilter + ")", func);
}
else if (selectFilter instanceof Array) {
for (var index in selectFilter) {
if (isAll) {
form.on("select(" + selectFilter[index] + ")", func);
}
else {
form.on("select(" + selectFilter[index] + ")", func);
break;
}
}
}

  1.  

}

  1.  

//有默认选项 处罚select事件
if (defaultValue) {
//以默认值触发监听事件
if (typeof defaultValue != "string" || defaultValue.indexOf("index_", 0)==-1) {
if (func instanceof Array) {
for (var index in func) {
func[index]({ value: defaultValue });
}
}
else {
func({ value: defaultValue });
}
}
//以选项的某个选项来触发监听事件
else {
var valueIndex = defaultValue.substring(defaultValue.length - 1, defaultValue.length);
if (func instanceof Array) {
for (var index in func) {
func[index]({ value: options[valueIndex][dataValue] });
}
}
else {
func({ value: options[valueIndex][dataValue] });
}
}
}
}
}
});
},

  1.  

table: function (obj) {

  1.  

var url = obj.url,//数据源Url
tableId = obj.tableId,//渲染完table的Id
contentId = obj.contentId,//容器div的Id
tableFilter = obj.tableFilter ? obj.tableFilter : contentId,//test是table原始容器的属性 lay-filter="对应的值",默认与Id相同
limits = obj.limits ? obj.limits : [10, 20, 50, 100, 200],//分页参数 默认10, 20, 50, 100, 200
cols = obj.cols,//表头及字段绑定
func = obj.doneFun,//表格渲染完回调函数
isPage = obj.isBackPage ? obj.isBackPage : false,//是否启用后台分页
toolBarEvent = obj.toolBarEvent,//头部工具栏事件
sortEvent = obj.sortEvent,//排序切换事件
ckboxEvent = obj.ckboxEvent,//选框选择事件
editEvent = obj.editEvent,//单元格编辑事件
toolEvent = obj.toolEvent,// 绑定行工具条事件
method = obj.method ? obj.method : 'post',//请求方式 默认post
where = obj.where ? obj.where : null,//请求额外参数
response = obj.response ? obj.response : {
statusName: 'code',
statusCode: 'success',
dataName: 'data',
countName: 'TotalPackageNum',
msgName: 'message'
},//返回参数名配置
request = obj.request ? obj.request : {
pageName: 'PageIndex',
limitName: 'PageSize'
};//请求参数名配置,默认PageIndex,PageSize

  1.  

var option = {
id: tableId,
elem: '#' + contentId,
page: true,
limits: limits,
cols: cols,
done: func
};

  1.  

if (isPage) {

option.method = method;
option.url = url;
option.where = where;
option.request = request;
option.response = response;
option.contentType = 'application/json';
option.loading = true;
}
else {
$.ajax({
url:url,
type: method,
data: where,
async:false,
contentType: 'application/json',
success: function (result) {
var data;
if (typeof (result) == 'string') {
data = JSON.parse(result);
}
else {
data = result;
}
if (data[response.statusName] == response.statusCode) {
option.data = data[response.dataName];
}

},
error: function (error) {

  1.  

layer.msg("网路错误");
}
});
}

  1.  

table.render(option);
if (toolBarEvent) {
table.on('toolbar(' + tableFilter + ')', toolBarEvent);
}
if (sortEvent) {
table.on('sort(' + tableFilter + ')', sortEvent);
}
if (ckboxEvent) {
table.on('checkbox(' + tableFilter + ')', ckboxEvent);
}
if (editEvent) {
table.on('edit(' + tableFilter + ')', editEvent);
}
if (toolEvent) {
table.on('tool(' + tableFilter + ')', toolEvent);
}

},

  1.  

//获取url中的参数
getQueryString: function (name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = decodeURI(window.options.search.substr(1)).match(reg);
if (r != null) return unescape(r[2]); return null;
},

  1.  

//Url参数封装成对象
convertUrlObj: function (url) {
var str;
if (url) {
str = url
}
else {
str = decodeURI(window.options.search.substr(1));
}

  1.  

var keyValues = str.split('&');
var obj = {};
for (var index in keyValues) {
var keyValue = keyValues[index].split('=');
obj[keyValue[0]] = keyValue[1];
}

  1.  

return obj;
},

  1.  

//封装form表单object
getFormObj: function (formId) {
var data = $("#" + formId).serializeArray();
var obj = {};
for (var key in data) {
obj[data[key].name] = data[key].value;
}
return obj;
}
};

// 错误弹出层
error: function (message) {
layer.open({
content: message,
icon: 2,
title: '错误提示'
});
},

//成功弹出层
success: function (message, func) {
layer.open({
content: message,
icon: 1,
yes: func
});
},

//二次确认框
confirm: function (message,func) {
layer.confirm(message, { icon: 3, title: '提示' }, function (index) {
func();
layer.close(index);
});
},

//文件下载(post无刷新)
downLoadFile: function (option) {
var method = option.method ? option.method : "post";
var $iframe = $('<iframe id="downFileFrame" name="" style="display:none;" scrolling="yes" noresize ></frame>');
var $form = $('<form method="' + method + '" action="' + option.url + '"></form>');
if (option.data) {
for (var key in option.data) {
$form.append('<input type="hidden" name="' + option.data[key].name + '" value="' + option.data[key].value + '"/>');
}
}
$iframe.append($form);
$(document.body).append($iframe);
$form[0].submit();
$iframe.remove();
}

  1.  

exports('common', extend);
});

  1.  

layui自定义模块使用:

注意:这里我们的自定义模块的文件最好和我们之后引入对象的名字一样,这样我们之后就不用指定文件。这里我的模块叫common,文件也叫common.js。

自定义模块的公用方法:

1.select下拉框渲染

用法:

  1. //始发仓下拉框
  2. common.select({
  3. url: '/api/Common/GetUserLocation',
  4. elemIds: ['locationId', 'simpleLocationId'],
  5. dataValue: 'LocationId',
  6. dataText: 'Location',
  7. defaultValue: "index_0",//默认选项(可以是具体某个option的value或text)
  8. otherOption: "<option value=''>全部</option>",//额外选项
  9. isLocalRender: true//开启局部渲染
  10. });

具体参数,请看common文件。这里支持局部渲染,前提是我们约定select标签规范

上述红框是开启局部刷新的必须条件,lay-filter默认和id一个名,可以不传。同时支持省市区三级联动,在传入id时,传入一个id数组。监听事件也可以是一个数组,可以选择多个控件绑定一个监听事件,或者一一对应的绑定。如下是三个省市区三级联动:

  1. //下拉框加载(省市区联动)
  2. common.select({
  3. url: "/api/Common/GetAllProvince",
  4. elemIds: ['provinceId', 'sourceProvinceId', 'targetProvinceId'],
  5. dataValue: 'RegionId',
  6. dataText: 'RegionName',
  7. defaultValue: "index_0",
  8. otherOption: "<option value=''>全部</option>",
  9. isLocalRender: true,
  10. selectFunc: [function (obj) {//简单快递规则 目的省联动 目的城市
  11. common.select({
  12. url: '/api/Common/GetRegionListByParentId',
  13. elemIds: 'cityId',
  14. requestdata: { parentId: obj.value },
  15. dataValue: 'RegionId',
  16. dataText: 'RegionName',
  17. defaultValue: "index_0",
  18. isLocalRender: true,
  19. otherOption: "<option value=''>全部</option>",
  20. selectFunc: function (obj) {//简单快递规则 目的城市联动 目的县区
  21. common.select({
  22. url: '/api/Common/GetRegionListByParentId',
  23. elemIds: 'districtId',
  24. requestdata: { parentId: obj.value },
  25. dataValue: 'RegionId',
  26. dataText: 'RegionName',
  27. defaultValue: "index_0",
  28. isLocalRender: true,
  29. otherOption: "<option value=''>全部</option>"
  30. });
  31. }
  32. });
  33. }, function (obj) {//复杂快递规则 始发省联动 始发城市
  34. common.select({
  35. url: '/api/Common/GetRegionListByParentId',
  36. elemIds: 'sourceCityId',
  37. requestdata: { parentId: obj.value },
  38. dataValue: 'RegionId',
  39. dataText: 'RegionName',
  40. isLocalRender: true,
  41. defaultValue: "index_0",
  42. otherOption: "<option value=''>全部</option>",
  43. selectFunc: function (obj) {//复杂快递规则 始发城市联动 始发区县
  44. common.select({
  45. url: '/api/Common/GetRegionListByParentId',
  46. elemIds: 'sourceDistrictId', sourceCityId,
  47. requestdata: { parentId: obj.value },
  48. dataValue: 'RegionId',
  49. dataText: 'RegionName',
  50. defaultValue: "index_0",
  51. otherOption: "<option value=''>全部</option>",
  52. isLocalRender: true
  53. });
  54. }
  55. });
  56. }, function (obj) {//复杂快递规则 目的省联动 目的城市
  57. common.select({
  58. url: '/api/Common/GetRegionListByParentId',
  59. elemIds: 'targetCityId',
  60. requestdata: { parentId: obj.value },
  61. dataValue: 'RegionId',
  62. dataText: 'RegionName',
  63. isLocalRender: true,
  64. defaultValue: "index_0",
  65. otherOption: "<option value=''>全部</option>",
  66. selectFunc: function (obj) {//复杂快递规则 目的城市联动 目的县区
  67. common.select({
  68. url: '/api/Common/GetRegionListByParentId',
  69. elemIds: 'targetDistrictId',
  70. requestdata: { parentId: obj.value },
  71. dataValue: 'RegionId',
  72. dataText: 'RegionName',
  73. defaultValue: "index_0",
  74. otherOption: "<option value=''>全部</option>",
  75. isLocalRender: true
  76. });
  77. }
  78. });
  79. }]
  80. });

2.table的使用

这里你可以选择用后台分页,或者前台分页,只用修改参数isBackPage。如果后台分页的话,需要指定request参数,默认是:

你可以根据自己的需要去绑定后台字段。直接上用法吧:

  1. //表头数据列
  2. var cols = [[
  3. { type: 'checkbox', align: 'center', style: 'top:7px', width: '5%' },
  4. { type: 'numbers', align: 'center', title: '编号', width: '10%', sort: true }
  5. ]];
  6. //数据列表加载
  7. common.table({
  8. url: '../api/DeliveryCost/ExpressCostRulesList',
  9. where: obj,
  10. tableId: 'dataTable',
  11. contentId: 'simpleList',
  12. cols: cols,
  13. isBackPage: true
  14. });

  

3.一些公用方法

1.如果你需要表单提交,获取表单内容而不是一个个$().val()去获取,可以使用getFormObj(),传入一个form的id,即可把表单封装成一个object。

2.如果你从一个页面传入到另外一个页面,如果参数比较少,或者想获取某个指定参数,可以用getQueryString。如果是整个表单传递过去,你可以用convertUrlObj,他会将url的key=value参数封装成一个

object。

3.convertUrlObj可以将url的key=value转换成obj.

4.一些公用的弹出框,包括success,error ,confirm

5.无刷新文件下载。

以上是我在使用layui的时候一些小经验,希望可以给一些朋友小小的帮助。自己记录下来,也是一个学习的过程,慢慢积累。加油!

layui二次封装的更多相关文章

  1. 对百度WebUploader开源上传控件的二次封装,精简前端代码(两句代码搞定上传)

    前言 首先声明一下,我这个是对WebUploader开源上传控件的二次封装,底层还是WebUploader实现的,只是为了更简洁的使用他而已. 下面先介绍一下WebUploader 简介: WebUp ...

  2. iOS项目相关@AFN&SDWeb的二次封装

    一,AFNetworking跟SDWebImge是功能强大且常用的第三方,然而在实际应用中需要封装用来复用今天就跟大家分享一下AFN&SDWeb的二次封装 1. HttpClient.h及.m ...

  3. Quick Cocos (2.2.5plus)CoinFlip解析(MenuScene display AdBar二次封装)

    转载自:http://cn.cocos2d-x.org/tutorial/show?id=1621 从Samples中找到CoinFlip文件夹,复制其中的 res 和 script 文件夹覆盖新建工 ...

  4. 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache

    虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...

  5. Android 应用程序集成Google 登录及二次封装

    谷歌登录API:  https://developers.google.com/identity/sign-in/android/ 1.注册并且登录google网站 https://accounts. ...

  6. Android 应用程序集成FaceBook 登录及二次封装

    1.首先在Facebook 开发者平台注册一个账号 https://developers.facebook.com/ 开发者后台  https://developers.facebook.com/ap ...

  7. 对jquery的ajax进行二次封装

    第一种方法: $(function(){ /** * ajax封装 * url 发送请求的地址 * data 发送到服务器的数据,数组存储,如:{"username": " ...

  8. AFNetworking二次封装的那些事

    AFNetworking可是iOS网络开发的神器,大大简便了操作.不过网络可是重中之重,不能只会用AFNetworking.我觉得网络开发首先要懂基本的理论,例如tcp/ip,http协议,之后要了解 ...

  9. volley二次封装

    产品中使用Volley框架已有多时,本身已有良好封装的Volley确实给程序开发带来了很多便利与快捷.但随着产品功能的不断增加,服务器接口的不断复杂化,直接使用Volley原生的JSONObjectR ...

随机推荐

  1. Codeforces Round #355 (Div. 2)C - Vanya and Label

    啊啊啊啊啊啊啊,真的是智障了... 这种题目,没有必要纠结来源.只要知道它的结果的导致直接原因?反正这句话就我听的懂吧... ">>"/"&" ...

  2. U3D 的一些基础优化

    1.在使用数组或ArrayList对象时应当注意 [csharp] view plaincopy length=myArray.Length; for(int i=0;i<length;i++) ...

  3. bzoj 5294: [Bjoi2018]二进制【动态dp+线段树】

    不太清楚是不是动态dp--? 这个维护其实和最大连续子段差不多,维护l[x][y],r[x][y],m[x][y]分别表示包含左儿子的01个数为(x,y)的区间个数,包含右儿子的01个数为(x,y)的 ...

  4. JZOJ4307. 【NOIP2015模拟11.3晚】喝喝喝

    Description

  5. eclipse | 配置JRE

    Window --> Preference --> Java ---> Installed JREs

  6. JAVA学习笔记(一)配置环境

    java语言的两种机制: Java 的虚拟机机制(JVM):虚拟机机制保证Java程序的跨平台特性. Java 的垃圾回收机制:垃圾回收机制保证Java程序更安全.更高效. 环境搭配:安装JDK和JR ...

  7. Windows下DVWA安装指南

    注意:DVWA需要依赖httpd.PHP.MySQL.php-mysql等应用或组件,最简单的方法是安装wampserver(http://www.wampserver.com/),安装完了所需的各种 ...

  8. h5-21-文件操作-读取文件内容

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. 关于web中的路径

    做了许多Demo发现,浏览器解析的路径和服务器解析的路径是不同的.我们知道,路径加上/的时候,表示的是绝对路径的意思,而如果是服务器解析的话,这个/相对的是我们的web应用,即相对于http://19 ...

  10. new几种用法

    在 C# 中,new 关键字可用作运算符.修饰符或约束. new 运算符 用于创建对象和调用构造函数. new 修饰符 用于向基类成员隐藏继承成员. new 约束 用于在泛型声明中约束可能用作类型参数 ...