EASY spa单页面版文档
1.1.导入项目
- 下载项目后进行解压
- 使用IDEA、WebStorm、HBuilder等前端开发工具打开
- 打开index.html点击右上角浏览器图标运行:
注意: 必须以http://的形式访问,而不是file://的形式访问。
1.2.项目结构
|-assets
| |-images // 图片
| |-js
| |-main.js // 入口js
| |-libs // 第三方库,echarts(图表)、layui
| |-module // layui扩展模块,版本更新只用替换此目录
| |-img // 框架用到的图片
| |-admin.css // 框架核心样式
| |-admin.js // admin模块
| |-index.js // index模块
| |-******** // 其他扩展模块,不一一列举
|-components // html子页面
|-json // 模拟数据
|-index.html // 主页面
main.js为入口js,上手使用项目前最好先看看它的说明。
1.3.index.html结构说明
<html>
<head><link rel="stylesheet" href="assets/libs/layui/css/layui.css"/><link rel="stylesheet" href="assets/module/admin.css"/>
</head>
<body class="layui-layout-body"><div class="layui-layout layui-layout-admin"><!-- 头部 --><div class="layui-header">...</div><!-- 侧边栏 --><div class="layui-side">...</div><!-- 主体部分 --><div class="layui-body">...</div><!-- 底部 --><div class="layui-footer">...</div></div><script type="text/javascript" src="assets/libs/layui/layui.js"></script><script type="text/javascript" src="assets/js/main.js"></script>
</body>
</html>
index.html就是这样固定的结构,一般不需要修改,只用在components下写子页面即可。
1.4.添加一个菜单
- 打开json/menus.json,在合适的位置添加一个菜单:
{"name": "xx管理", "url": "#/xxx"}
- 在components下面新建一个xxx.html页面
- 运行index.html,查看效果
3.1.6版本开始菜单支持更丰富的写法:
[{"name": "xx管理","url": "#/xxx""show": false
}, {"name": "百度","url": "#/baidu","iframe": "https://baidu.com"
}, {"name": "layui","url": "https://layui.com","target": "_blank"
}]
- show false表示只注册路由,不显示在侧边栏
- iframe 表示用iframe打开一个标签
- target 表示当url不受路由控制时在新窗口打开链接
注意: url以"#/"开头才会受路由控制,实现局部加载。
1.5.main.js说明
layui.config({version: true, // 版本号配置为true可解决页面缓存问题base: 'assets/module/' // 配置layui扩展模块目录
}).extend({ // 配置每个模块分别所在的目录notice: 'notice/notice',steps: 'steps/steps'
}).use(['index', 'admin'], function () {var $ = layui.jquery;var index = layui.index;var admin = layui.admin;// 加载侧边栏admin.req('menus.json', function (res) {index.regRouter(res); // 注册路由index.renderSide(res); // 渲染侧边栏// 加载主页index.loadHome({url: '#/console/console',name: '<i class="layui-icon layui-icon-home"></i>'});});});
- layui.config是告诉layui扩展模块所在目录
- layui.extend是配置每个模块具体位置,像admin.js、index.js这些没有子目录的不用配置
- version:true可解决模块js、html页面缓存的问题,也可以配置一个固定的版本号
main.js的业务流程为先通过ajax加载菜单json,然后注册路由、渲染侧边栏、加载主页,至此框架即成功运行了。
如果不是前后端分离的项目,base怎么配置加载模块都是404,建议这样配置:
layui.config({base: getProjectUrl() + 'assets/module/'
})/* 获取项目根路径 */
function getProjectUrl() {var layuiDir = layui.cache.dir;if (!layuiDir) {var js = document.scripts, last = js.length - 1, src;for (var i = last; i > 0; i--) {if (js[i].readyState === 'interactive') {src = js[i].src;break;}}var jsPath = src || js[last].src;layuiDir = jsPath.substring(0, jsPath.lastIndexOf('/') + 1);}return layuiDir.substring(0, layuiDir.indexOf('assets'));
}
getProjectUrl()方法原理是获取layui.js的全路径,并截取assets之前的路径,所以layui需要在assets目录下面, assets上一层需要是项目根路径,或者根据你的目录结构合理修改getProjectUrl方法,比如assets改成static。
1.6.setter模块
setter模块主要是用于给index模块和admin模块提供配置,可根据自己需要进行更改。
参数:
配置名 | 默认 | 说明 |
---|---|---|
baseServer | 'json/' | 接口地址,admin.req方法会自动加 |
tableName | 'easyweb-spa' | 前端缓存用的存储表名 |
pageTabs | false | 是否开启多标签 |
cacheTab | true | 是否记忆Tab |
openTabCtxMenu | true | 是否开启Tab右键菜单 |
maxTabNum | 20 | 最多打开多少个tab |
viewPath | 'components' | 视图位置 |
viewSuffix | '.html' | 视图后缀 |
defaultTheme | 默认主题 | |
reqPutToPost | true | req请求put方法变成post,delete变get,并自动加_method |
apiNoCache | true | 配置为true后ajax请求json数据不会加版本号 |
navArrow | 侧边栏导航箭头,可选''(layui默认)、'arrow2'(箭头)、'arrow3'(加减号) | |
closeFooter | false | 是否关闭页脚 |
tplOpen | '{{' | 模板引擎边界符 |
tplClose | '}}' | 模板引擎边界符 |
tabAutoRefresh | false | 是否切换Tab自动刷新页面 |
defaultLoading | 1 | 默认的加载动画(只控制admin.showLoading的默认) |
方法:
配置名 | 默认 |
---|---|
getToken() | 获取token |
putToken(token) | 缓存token |
removeToken() | 清除token |
getUser() | 获取当前登录的用户信息 |
putUser(user) | 缓存当前登录的用户信息 |
getUserAuths() | 获取用户所有权限 |
getAjaxHeaders(requestUrl) | ajax请求的统一header |
ajaxSuccessBefore(res, requestUrl) | ajax请求结束后的统一预处理 |
routerNotFound(r) | 路由不存在处理 |
setter模块里面的配置都是默认配置,如果在主题界面修改了配置会以主题界面操作的为主,主题界面的操作保存在本地缓存中, 清除浏览器缓存就会以setter模块里面配置的为主。
table需要在setter.js最下面用table.set实现自动传递header和预处理:
layui.define(['table'], function (exports) {var setter = {};/* table全局设置 */var token = setter.getToken();if (token && token.access_token) {layui.table.set({headers: {'Authorization': 'Bearer ' + token.access_token},parseData: function(res) { // 利用parseData实现预处理if(res.code == 401) {setter.removeToken();layui.layer.msg('登录过期', {icon: 2, anim: 6, time: 1500}, function () {location.replace('components/template/login/login.html');});}return res;}});}exports('setter', setter);
});
dataGrid和treeTable组件是支持参数配置使用admin.ajax的发送请求的。
或者使用$.ajaxSetup
统一处理:
$.ajaxSetup({complete: function (xhr) {try {var res = JSON.parse(xhr.responseText);if (1131 === res.code || 1122 === res.code || 1120 === res.code) { // 登录过期setter.removeToken();layui.layer.msg('登录过期', {icon: 2, anim: 6, time: 1500}, function () {location.replace('components/template/login/login.html');});}} catch (e) {}}
});
注意: layui更新到2.5.6后模块名不能使用config,所以config.js现在改成了setter.js,请注意修改
// 老版本只用把前面两行的config改成setter就可以了
layui.use(['setter'], function(){var config = layui.setter;
});
/*
layui.use(['config'], function(){var config = layui.config;
});
*/
1.7.ID命名规范
SPA单页面应用如果有重复的ID会出现问题,所有的页面都不能有重复的ID,因为是jQuery系的框架,id还是很常用的, 为了避免ID出现重复,强烈建议按照一定规范来命名。
总体命名规则xxxXxxXxx
- 第一个xxx 模块名,比如用户模块
user
- 第二个Xxx 功能描述,比如添加
Add
- 第三个Xxx 元素类型,比如按钮
Btn
例如页面是user.html,它的各个元素命名如下:
按钮的命名
<!-- 命名规则:xxxXxxBtn -->
<button id="userAddBtn" class="layui-btn">添加</button>
<button id="userEditBtn" class="layui-btn">修改</button>
<button id="userDelBtn" class="layui-btn">删除</button>
表格的命名
<!-- 命名规则:xxxTable -->
<table id="userTable" lay-filter=""userTable"></table><!-- 表格上方搜索表单,命名规则:xxxTbSearchForm,id和lay-filter是非必须的 -->
<form class="layui-form" id="userTbSearchForm" lay-filter="userTbSearchForm"><!-- 输入框部分省略... --><!-- 搜索提交按钮命名规则:xxxTbSearch --><button class="layui-btn" lay-filter="userTbSearch" lay-submit>搜索</button>
</form><!-- 表格操作列,命名规则:xxxTbBar -->
<script type="text/html" id="userTbBar"><a class="layui-btn" lay-event="edit">修改</a><a class="layui-btn" lay-event="del">删除</a>
</script><!-- 表格其他复杂列,例如switch状态开关等,命名规则:xxxTbXxx -->
<script type="text/html" id="userTbState"><input type="checkbox" lay-filter="userTbStateCk" value="{{d.userId}}" lay-skin="switch"lay-text="正常|锁定" {{d.state==0?'checked':''}}/>
</script>
一个页面有多个表格的命名
<!-- 命名规则:xxxXxxTable -->
<!-- 例如这是一个用户订单记录表 -->
<table id="userOrderTable" lay-filter=""userOrderTable"></table><!-- 表格操作列,命名规则:xxxXxxTbBar -->
<script type="text/html" id="userOrderTbBar"><a class="layui-btn" lay-event="edit">修改</a><a class="layui-btn" lay-event="del">删除</a>
</script>
表单弹窗的命名
<!-- 页面层弹窗命名规则:xxxEditDialog,非页面层可以忽略script -->
<script type="text/html" id="userEditDialog"><!-- 表单命名规则:xxxEditForm --><form id="userEditForm" lay-filter="userEditForm" class="layui-form model-form"><!-- 输入框部分省略... --><!-- 提交按钮命名规则:xxxEditSubmit --><button class="layui-btn" lay-filter="userEditSubmit" lay-submit>保存</button></form>
</script>
页面其他弹窗的命名
<!-- 例如这是一个查看详情弹窗 -->
<!-- 页面层弹窗命名规则:xxxXxxDialog,非页面层可以忽略script -->
<script type="text/html" id="userInfoDialog"><!-- 表单命名规则:xxxXxxForm --><form id="userInfoForm" lay-filter="userInfoForm" class="layui-form model-form"><!-- 输入框部分省略... --><!-- 提交按钮命名规则:xxxXxxSubmit --><button class="layui-btn" lay-filter="userInfoSubmit" lay-submit>保存</button></form>
</script>
表单里面的input建议少用id,只用name,取input的值通过监听表单提交来取,用input通过$('#xxxForm [name="xxx"]')
来写。
其他元素ID命名
<!-- 命名规则:xxxXxxXxx,第一个xxx是模块名,第二个Xxx是功能描述,第三个Xxx是元素类型 --><!-- 例如角色选择的下拉框 -->
<select id="userRoleSel"></select><!-- 例如备注的输入框 -->
<input id="userCommentsEdt" />
元素类型简写
元素 | 简写 | 描述 |
---|---|---|
按钮类 |
Btn
|
<button> 、.layui-btn 等
|
输入类的 |
Edt
|
EditText的简写,input 、textarea 等
|
选择类的 |
Sel
|
下拉框、多选下拉框等 |
表格 |
Table
|
id="userTable" 、id="userOrderTable" 等
|
表格附加组件 |
Tb
|
id="userTbBar" 、id="userOrderTbBar" 等
|
弹窗 |
Dialog
|
id="userEditDialog 、id="userInfoDialog" 等
|
表单 |
Form
|
id="userEditForm 、id="userInfoForm" 等
|
表单提交按钮 |
Submit
|
id="userEditSubmit" 、id="userInfoSubmit" 等
|
页面的命名
<!-- 命名格式:xxxApp -->
<div class="layui-fluid" id="userApp"><!-- 省略页面内容...... -->
</div>
以上规则只是规范,非必须要求
1.8.子页面模板语法
在子页面首行增加<tpl/>
标签即可开启模板引擎:
<tpl/>
<style>
</style>
<div class="layui-fluid">{{# if(d.search.id==1){ }}<span>aaa</span>{{# }else{ }}<span>bbb</span>{{# } }}
</div>
<script>
</script>
用法与laytpl一致,边界符可以在setter.js中修改,d表示的是当前路由信息,例如访问 #/system/user/id=1/sex=男
它的路由信息为:
{path: ["system", "user"],search: {id: 1, sex: "男"},href: "/system/user/id=1/sex=男",refresh: false
}
- path 路径数组
- search 参数列表
- refresh 如果是刷新触发的值为true
也不一定只有d能用,比如获取layui版本号:{{layui.v}}
2.1.批量注册路由
index.regRouter([{name: '用户管理',url: '#/system/user' // 路由关键字,必须要有#号
}]);// 嵌入iframe网页形式
index.regRouter([{name: '百度一下',url: '#/baidu',iframe: 'https://baidu.com'
}]);// 格式化数据,可以处理后端返回的menu.json格式
index.regRouter(res.data, function (d) {d.name = d.menuName;d.url = d.path;d.iframe = d.component;d.icon = d.menuIcon;d.show = !d.hide;d.subMenus = d.children;return d;
});
参数是一个数组,当你访问#/system/user
时,就会打开一个“用户管理”标签页,“url”是路由关键字, 对应的页面地址是“components/system/user.html”,“components”和“.html”可以在setter模块中配置。
2.2.加载默认主页
index.loadHome({url: '#/console/console1',name: '<i class="layui-icon layui-icon-home"></i>',loadSetting: true
});
- url 必填,主页路径,必须要有#号
- name 必填,Tab标题
- iframe 非必填,嵌入iframe网页形式
- loadSetting 非必填,是否恢复记忆的Tab
只有调用了loadHome方法,路由模块才会真正开始工作。
2.3.打开一个选项卡
index.openNewTab({name: '用户管理', url: '#/system/user'
});// 也可以加参数
index.openNewTab({name: '用户管理', url: '#/system/user/id=1'
});// 打开一个iframe标签
index.openNewTab({name: '百度一下', url: '#/baidu',iframe: 'https://baidu.com'
});
- name 选项卡的标题
- url 路由关键字,必须要有#号
- iframe 可选参数,打开一个iframe标签
也可以使用<a href="#/system/user">XX</a>
,这种写法必须保证“#/system/user”已经注册了路由,而“openNewTab()”会自动注册。
注意:openNewTab方法只是注册临时路由,如果刷新页面,路由就会不存在了,
如果想刷新页面也能使用,需要提前在main.js中的index.loadHome()
方法之前注册路由, 或者在menus.json中配置,并且可以加show: false
不在侧边栏中显示。
2.4.关闭指定选项卡
index.closeTab('#/system/user');
index.closeTab('/system/user');
index.closeTab('system/user');
#/
可写可不写,关闭当前tab可以用admin.closeThisTabs()
或者ew-event="closeThisTabs"
。
2.5.跳到指定选项卡
index.go('#/system/user');
index.go('/system/user');
index.go('system/user');
前面#/
可写可不写。
2.6.修改Tab标题
index.setTabTitle('Hello'); // 修改当前Tab标题文字,也支持单标签模式index.setTabTitle('Hello', tabId); // 修改指定Tab标题文字index.setTabTitleHtml('<span>Hello</span>'); // 修改整个标题栏的html,此方法只在单标签模式有效index.setTabTitle(); // 单标签模式隐藏标题栏
关闭多标签会自动生成一个标题栏,可用此方法修改标题栏,参数为undefined
为隐藏标题栏。
2.7.获取hash路径
index.getHashPath('#/system/user');index.getHashPath('#/system/user/id=1/name=aa');
这两种hash最后返回的都是system/user
,后面属于参数传递,不属于视图的路径。
2.8.侧边栏手风琴折叠
在layui-nav-tree上面增加lay-shrink="_all"
配置即可展开菜单时收缩兄弟节点:
<!-- 侧边栏 -->
<div class="layui-side"><div class="layui-side-scroll"><ul class="layui-nav layui-nav-tree" lay-shrink="all">......省略其他部分</ul></div>
</div>
注意:是_all
而不是all
,在3.1.6版本之前是lay-accordion="true"。
2.9.切换Tab自动刷新
setter.js里面配置tabAutoRefresh: true
即可开启。
2.10.渲染侧边栏
3.1.6版本开始在index模块封装了渲染侧边栏方法,不用自己写laytpl渲染:
admin.req('menus.json', {}, function (res) {index.renderSide(res); // 渲染侧边栏
}, 'get');
该方法还提供了灵活自定义操作,比如多系统模式,自定义要怎么插入渲染完的html:
index.renderSide(res, $('#sideNav').html(), function(html, obj){// html 是渲染后的内容// obj.data 可获取处理后的数据,比如移除了show: false的数据// obj.side 是侧边栏的dom,例如$(obj.side + '>.layui-nav').html(html)// obj.render() 可更新nav的渲染
}, '{{', '}}');
- 参数一 必填,数据
- 参数二 非必填,html模板
- 参数三 非必填,hyml渲染完的自定义处理
- 参数四 非必填,模板引擎边界符
- 参数五 非必填,模板引擎边界符
index.renderSide一般写在index.regRouter之后,index.regRouter还可以格式化数据
3.1.全部方法
方法 | 参数 | 描述 |
---|---|---|
flexible(expand) | true和false | 折叠/展开侧导航 |
activeNav(url) | a标签的href无#号 | 设置侧导航栏选中 |
refresh(url) | url,可为空 | 刷新指定Tab或当前Tab |
closeAllTabs() | 无 | 关闭所有选项卡 |
closeOtherTabs(url) | url | 关闭除url外所有选项卡 |
closeThisTabs(url) | url,可为空 | 关闭url或当前选项卡 |
rollPage(d) | left、right、auto | 滚动选项卡tab |
changeTheme(theme,win,noCache,noChild) | 切换主题 | |
lockScreen(url) | 见单独 | 锁屏 |
unlockScreen(isRemove) | 见单独 | 解除锁屏 |
iframeAuto() | 无 | 让当前的iframe弹层自适应高度 |
closeThisDialog() | 无 | 关闭当前iframe弹窗 |
closeDialog(elem) | dom选择器 | 关闭elem元素所在的页面层弹窗 |
open(option) | 同layer | 打开弹窗 |
popupRight(option) | 同layer | 打开右侧弹窗 |
getLayerData(index,key) | 见弹窗专题 | 获取弹窗传递数据 |
putLayerData(key,value,index) | 见弹窗专题 | 弹窗传递数据 |
reloadLayer(index,url,success) | 见弹窗专题 | 刷新url方式弹窗 |
alert(content,options,yes) | 同layer | 封装layer.alert |
confirm(content,options,yes,cancel) | 同layer | 封装layer.confirm |
prompt(options,yes) | 同layer | 封装layer.prompt |
tips(options) | 见admin模块高级 | 增强layer.tips |
modelForm(layero,btnFilter,formFilter) | 见弹窗专题 | 把弹窗自带按钮跟表单绑定一起 |
getLayerIndex('#elem') | jq选择器 | 获取页面层弹窗index |
req(url,data,success,method,option) | 见单独 | 封装ajax |
ajax(option) | 同$.ajax | 封装ajax |
showLoading(elem,type,opacity,size) | 见单独 | 显示加载动画 |
removeLoading(elem,fade,del) | 见单独 | 移除加载动画 |
btnLoading(elem,text,loading) | 见单独 | 设置按钮为加载状态 |
putTempData(key,value,local) | 见单独 | 缓存数据 |
getTempData(key,local) | 见单独 | 获取缓存数据 |
putSetting(key,value) | 修改配置信息 | |
recoverState() | 恢复配置信息 | |
getPageHeight() | 无 | 获取浏览器高度 |
getPageWidth() | 无 | 获取浏览器宽度 |
chooseLocation(option) | 见admin模块高级 | 地图选择位置 |
cropImg(option) | 见admin模块高级 | 裁剪图片 |
strToWin(str) | 字符的parent.parent转对象 | |
openSideAutoExpand() | 无 | 开启鼠标移入侧边栏自动展开 |
openCellAutoExpand() | 无 | 开启鼠标移入单元格超出自动展开 |
util.Convert_BD09_To_GCJ02(point) | 见admin模块高级 | 百度地图坐标转高德地图坐标 |
util.Convert_GCJ02_To_BD09(point) | 见admin模块高级 | 高德地图坐标转百度地图坐标 |
util.animateNum(elem,isThd,delay,grain) | 见admin模块高级 | 动态数字 |
util.deepClone(obj) | 见admin模块高级 | 深度克隆对象 |
util.fullTextIsEmpty(text) | 见admin模块高级 | 判断富文本是否为空 |
util.removeStyle(elem,options) | 见admin模块高级 | 移除元素的style |
util.scrollTop(elem) | 见admin模块高级 | 滚动到顶部 |
util.tpl(html,data,openCode,closeCode) | 见admin模块高级 | 模板解析 |
hasPerm(auth) | 权限 | 判断当前登录的用户是否有权限 |
renderPerm() | 无 | 移除没有权限的dom元素 |
使用示例:
layui.use(['admin'], function () {var admin = layui.admin;var pageHeight = admin.getPageHeight(); // 获取浏览器高度
});
3.2.弹窗相关方法
open和popupRight方法:
// 打开弹窗
admin.open({type: 2,content: 'tpl-theme.html'
});// 打开右侧面板
admin.popupRight({type: 2,content: 'tpl-theme.html'
});
这两个方法只是对layer.open进行了一层封装,参数和layer一样,查看layer文档。
新增参数url:
admin.open({ title: 'Hello',url: 'tpl-theme.html'
});admin.popupRight({ url: 'tpl-theme.html'
});
type:2, content:xxx
这种是iframe类型的弹窗,使用url
会通过ajax加载页面到弹窗中,而不是iframe嵌入。 当使用url方式的时候,弹窗页面应该是代码片段,而不是完整的html,如下所示:
<style>
* { color: red; }
</style>
<div class="layui-form model-form"><button class="layui-btn" ew-event="closeDialog">关闭我</button>
</div>
<script>layui.use(['layer', 'form'], function () {var $ = layui.jquery;});
</script>
页面不需要html、body这些东西,并且可以直接用<script>
标签来写事件。
admin.iframeAuto()方法:
针对type:2的弹窗自适应弹窗高度,写在弹窗的子页面中,此方法是调用一次做一次高度自适应, 如果你用js动态修改了弹窗子页面的高度,需要再调用一次。
admin.closeThisDialog():
关闭当前iframe类型弹窗,针对type:2的弹窗,在弹窗的子页面调用即可关闭当前的iframe弹窗。
admin.closeDialog('#xxx'):
关闭非iframe类型的弹窗,调用需要传递弹窗页面里面任意一个的元素。
关闭弹窗还可以使用ew-event
操作:
<!-- 关闭弹窗(智能) -->
<button ew-event="closeDialog"></button>
<!-- 关闭iframe类型的弹窗 -->
<button ew-event="closeIframeDialog"></button>
<!-- 关闭页面层的弹窗 -->
<button ew-event="closePageDialog"></button>
使用url方式更符合单页面,admin模块还封装了弹窗参数传递等更多方法,请到弹窗专题查看。
3.3.加载层loading
按钮loading:
admin.btnLoading('#btn1'); // 设置按钮为loading状态
admin.btnLoading('#btn1', false); // 移除按钮的loading状态admin.btnLoading('#btn1', ' 保存...'); // 设置按钮为loading状态,同时修改按钮文字
页面加载层:
admin.showLoading('#xxx'); // 在id为xxx的元素中显示加载层
admin.showLoading('#xxx', 1, '.8'); // 显示type为1、透明度为0.8的遮罩层// 尺寸控制,提供有两种尺寸,默认是sm小型尺寸,还可以选md大型尺寸
admin.showLoading({elem: '#xxx',type: 1,size: 'sm'
});
- 参数一
elem
非必填 元素选择器,不填为body - 参数二
type
非必填 动画类型(1 小球,2 魔方,3信号,4简约),默认1 - 参数三
opacity
非必填 透明度(0 - 1),默认不透明 - 参数四
size
非必填 尺寸,默认sm
移除加载动画:
admin.removeLoading('#xxx');
admin.removeLoading('#xxx', true, true);
- 参数一 非必填 元素选择器,不填为body
- 参数二 非必填 true是淡出效果,false直接隐藏,默认是true
- 参数三 非必填 true是删除,false是隐藏不删除,默认是false
页面载入的加载动画:
<body class="page-no-scroll"> <!-- page-no-scroll这个不要忘了 --><!-- 小球样式 --><div class="page-loading"><div class="ball-loader"><span></span><span></span><span></span><span></span></div></div><!-- 魔方样式 --><div class="page-loading"><div class="rubik-loader"></div></div><!-- 信号样式 --><div class="page-loading"><div class="signal-loader"><span></span><span></span><span></span><span></span></div></div><!-- 简约样式 --><div class="page-loading"><div class="layui-loader"><i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i></div></div><!-- 加sm是小型尺寸 --><div class="page-loading"><div class="signal-loader sm"><span></span><span></span><span></span><span></span></div></div>
</body>
写在页面中需要在js中调用admin.removeLoading()
移除加载动画。
3.4.ajax封装
req方法:
admin.req('url', {username: 'admin',password: '123456'
}, function(res){alert(res.code + '-' + res.msg);
}, 'get', { headers: {} });
- 参数一 请求的url,前面会自动加setter.baseServer
- 参数二 非必填,请求参数
- 参数三 请求回调(网络错误也进此回调,404、403等)
- 参数四 非必填,请求方式,get、post、put、delete等,默认get
- 参数五 非必填,ajax的更多参数,如headers、dataType等
req的这五个参数是自动像左补齐的,可以简写:
// 无参数,get请求
admin.req('url', function(res){console.log(res);
});// post提交
admin.req('url', function(res){console.log(res);
}, 'post');admin.req('url', {username: 'xxx',password: '123456'
}, function(res){console.log(res);
}, 'post');// 参数使用JSON.stringify()会自动增加contentType为json
admin.req('url', JSON.stringify(obj), function(res){console.log(res);
}, 'post');// 相当于
admin.req('url', JSON.stringify(obj), function(res){console.log(res);
}, 'post', {contentType: 'application/json'
});// 参数使用表单序列化
admin.req('url', $('#demoForm').serialize(), function (res) {console.log(res);
}, 'post', {contentType: 'application/x-www-form-urlencoded'
});
ajax方法,参数同$.ajax:
admin.ajax({url: 'url',data: {},headers: {},type: 'post',dataType: 'json',success: function(res){alert(res.code + '-' + res.msg);}
});
自动传递header和预处理:
在module/setter.js
(原config.js)中通过下面两个方法操作:
var setter = {// 自动传递headergetAjaxHeaders: function (url) {var headers = [];headers.push({name: 'token', value: 'xxxxx'});return headers;},// 请求完成后预处理ajaxSuccessBefore: function (res, url, obj) {if(res.code == 401) {alert('登录超时,请重新登录');// obj.reload(); // 重新发起请求// obj.update({}); // 修改res数据// obj.xhr // ajax原始的xhr对象return false; // 返回false阻止代码执行}return true;}
};
req和ajax都实现了自动传递header、预处理、网络错误也回调到success(404、500等错误)。
3.5.缓存操作putTempData
admin.putTempData('key', 'value'); // sessionStorage存储
admin.putTempData('key'); // 不写value是删除
admin.putTempData('key', 'value', true); // localStorage存储
admin.putTempData('key', true); // 不写value是删除admin.getTempData('key'); // 获取sessionStorage存储的key
admin.getTempData('key', true); // 获取localStorage存储keyadmin.getTempData(); // 获取sessionStorage存储的全部数据
admin.getTempData(true); // 获取localStorage存储的全部数据
3.6.锁屏功能
admin.lockScreen(url); // 锁屏,url是锁屏页面地址,不填为默认地址admin.unlockScreen(); // 解除锁屏(隐藏锁屏页面)admin.unlockScreen(true); // 移除锁屏页面,下次锁屏需要重新加载页面
如果是自定义锁屏页面,页面不要包含head、body这些东西,只是代码片段,参考默认的锁屏页面。
3.7.ew-event事件绑定
使用示例:
<a ew-event="fullScreen">全屏</a>
<a ew-event="flexible">折叠导航</a>
事件 | 描述 |
---|---|
flexible | 折叠侧导航 |
refresh | 刷新主体部分 |
closeThisTabs | 关闭当前选项卡 |
closeOtherTabs | 关闭其他选项卡 |
closeAllTabs | 关闭全部选项卡 |
leftPage | 左滚动选项卡 |
rightPage | 右滚动选项卡 |
closeDialog | 关闭当前弹窗(智能) |
closeIframeDialog | 关闭当前iframe层弹窗 |
closePageDialog | 关闭当前页面层弹窗 |
theme | 打开主题设置弹窗 |
note | 打开便签弹窗 |
message | 打开消息弹窗 |
psw | 打开修改密码弹窗 |
logout | 退出登录 |
fullScreen | 全屏切换 |
back | 浏览器后退 |
lockScreen | 锁屏 |
open | 打开弹窗 |
popupRight | 打开右侧弹窗 |
ew-event属性可用于任何元素,不仅仅是a标签,theme、note等可以通过data-url
属性配置对应的url, 还可以通过data-window="top"
属性配置在父页面处理事件。
<a ew-event="theme" data-url="xxx.html" data-window="parent">主题</a>
自定义事件,添加下面代码即可,建议放在main.js中:
admin.events.xxx = function(){layer.msg($(this).text());
}
<a ew-event="xxx">测试</a>
3.8.open弹窗事件
open和popupRight这两个事件是用来支持非js方式打开弹窗:
<button ew-event="open" data-type="2" data-content="http://baidu.com">iframe弹窗</button><button ew-event="open" data-type="1" data-url="form.html">页面弹窗</button><button ew-event="open" data-type="1" data-content="#userForm">页面弹窗</button>
<form id="userForm">......省略</form><!-- 设置area和offset -->
<button ew-event="open" data-type="1" data-content="Hello" data-area="80px,60px" data-offset="10px,10px">页面弹窗</button><!-- popupRight一样的用法 -->
<button ew-event="popupRight" data-type="2" data-url="http://baidu.com" data-title="百度一下,你就知道">右侧弹窗</button><!-- function类型参数写法,success、end等 -->
<button ew-event="open" data-type="1" data-content="Hello" data-success="onDialogSuccess">页面弹窗</button>
<script>layui.use(['layer'], function(){var layer = layui.layer;// 方法需要加windowwindow.onDialogSuccess = function(){layer.msg('弹窗被成功打开了'); };});
</script><!-- 加data-window="top"相当于top.layui.admin.open -->
<button ew-event="open" data-type="2" data-content="http://baidu.com" data-window="top">iframe弹窗</button>
layer支持的参数大部分都可以通过data属性来设置,数组类型用逗号分隔,function类型需要把作用域放在window对象下, 也可以直接写js比如data-success="layer.msg('打开了弹窗')"
。
3.9.logout事件
<a ew-event="logout" data-url="login.html" data-ajax="api/logout"data-method="post"data-code="200"data-parse-data="return {code: res.status, msg: res.message}"data-confirm="false">退出登录</a>
- data-url 必填 退出登录后跳转的页面地址
- data-ajax 非必填 退出登录需要请求的ajax接口
- data-method 非必填 ajax请求方式,默认是delete
- data-code 非必填 ajax返回成功的状态码,默认是0
- data-parse-data 非必填 处理接口返回的数据
- data-confirm 非必填 是否显示询问框,false表示直接退出不询问,默认true
3.10.判断权限hasPerm
通过admin.hasPerm(auth)
可以控制按钮级别的权限隐藏:
if(!admin.hasPerm('user:add')) {$('#btnUserAdd').remove();
}
- hasPerm方法需要通过
setter.getUserAuths
方法来获取全部权限 - setter.getUserAuths是通过
setter.getUser
方法从用户信息中获取权限的 - setter.getUser是从本地缓存中获取用户信息的,
setter.putUser
把用户信息放入缓存中
在main.js中有获取用户信息并通过setter.putUser
放入缓存中的写法。
还可以通过加属性的方式来隐藏:
<button perm-show="user:add">添加</button>
perm-show
可以用于任意元素,对于动态添加的元素调用admin.renderPerm()
来更新渲染,比如表格应该写在done回调里面:
table.render({elem: '#userTable',url: '../../json/user.json',toolbar: ['<div>','<button perm-show="user:add" lay-event="add" class="layui-btn">添加</button>','<button perm-show="user:del" lay-event="del" class="layui-btn">删除</button>','</div>'].join(''),cols: [[{type: 'numbers'},{field: 'username', title: '账号', sort: true},{field: 'nickName', title: '用户名', sort: true},{title: '操作', toolbar: '#userTbBar', align: 'center', minWidth: 200}]],done: function() {admin.renderPerm();}
});
4.1.文字提示
鼠标滑过弹出tips,使用示例:
<button lay-tips="大家好!">按钮</button><button lay-tips="大家好!" lay-direction="2" lay-bg="#009788">按钮</button><button lay-tips="大家好!" lay-offset="10px" lay-bgImg="linear-gradient(to right,#8510FF,#D025C2,#FF8B2D,#F64E2C)">按钮</button><button lay-tips="大家好!" lay-offset="-10px,-10px" lay-padding="5px">按钮</button>
- lay-direction: 设置位置,1上面(默认)、2右边、3下面、4左边
- lay-bg: 设置背景颜色(包含箭头颜色,下面的背景图片不包含箭头)
- lay-offset: 设置偏移距离,(上,左)
- lay-padding:内间距
- lay-color:文字颜色
- lay-bgImg:背景图片,例如lay-bgImg="url(assets/images/head.jpg)"
- lay-fontSize:字体大小
除了elem和text其他都是可选参数,还可以使用admin.tips()
直接调用:
admin.tips({elem: '#btn', text: 'Hello', direction: 3, bg: '#803ed9',offset: '-10px,-10px', padding: '15px', color: '#eee',bgImg: 'linear-gradient(to right,#8510FF,#D025C2,#FF8B2D,#F64E2C)',fontSize: '18px', tipsMore: true, time: -1
});
4.2.地图选择位置
admin.chooseLocation({needCity: true,onSelect: function (res) {layer.msg(JSON.stringify(res), {icon: 1});}
});
参数 | 默认 | 描述 |
---|---|---|
title | "选择位置" | 弹窗标题 |
needCity | false | 是否返回行政区,省市区默认不返回 |
center | 定位当前城市 | 地图默认的中心点 |
defaultZoom | 11 | 地图默认缩放级别 |
pointZoom | 17 | 选中时地图的缩放级别 |
keywords | 无 | poi检索关键字,例如:建筑、写字楼 |
pageSize | 30 | poi检索最大数量 |
onSelect | 无 | 选择回调 |
mapJsUrl | 内置 | 高德地图js的url |
- 地图默认中心点参考值:[116.397428, 39.90923],经度,纬度
- 地图url参考值:
https://webapi.amap.com/maps?v=1.4.14&key=xxxxxxx
- 返回结果说明:
- res.name; // 地点名称
- res.address; // 详细地址
- res.lat; // 纬度
- res.lng; // 经度
- res.city; // 城市,是一个对象
- res.city.province; // 省
- res.city.city; // 市
- res.city.district; // 区
- res.city.citycode; // 城市代码
地图相关参数的详细介绍请前往高德地图API查看。
4.3.裁剪图片
admin.cropImg({aspectRatio: 1/1,imgSrc: '../../assets/images/15367146917869444.jpg',onCrop: function (res) {// 返回的res是base64编码的裁剪后的图片layer.msg('<img src="' + res + '" width="220px" height="220px"/>');}
});
参数 | 默认 | 描述 |
---|---|---|
title | "裁剪图片" | 弹窗标题 |
aspectRatio | 1/1 | 裁剪比例,例如:16/9 |
imgSrc | 无 | 要裁剪的图片,无则先弹出选择图片 |
imgType | 'image/jpeg' | 裁剪的图片类型,非必填 |
onCrop | 无 | 裁剪完成回调 |
limitSize | 不限制 | 限制选择的图片大小 |
acceptMime | 'image/*' | 限制选择的图片类型 |
exts | 不限制 | 限制选择的图片后缀 |
- acceptMime参考值:'image/jpg, image/png'(只显示 jpg 和 png 文件)
- exts参考值:jpg|png|gif|bmp|jpeg
后面三个参数配置可参考upload模块, 如果想单独在页面中使用图片裁剪功能请参考Cropper插件文档
4.2.动画数字
<h2 id="demoAnimNum1">12345</h2>
<h2 id="demoAnimNum2">¥2373467.342353</h2>
<h2 id="demoAnimNum3">上浮99.98%</h2><script>
layui.use(['admin'], function () {var $ = layui.jquery;var admin = layui.admin;admin.util.animateNum('#demoAnimNum1');admin.util.animateNum('#demoAnimNum2');admin.util.animateNum('#demoAnimNum3', true, 500, 100);
});
</script>
- 参数一 需要动画的元素
- 参数二 是否开启千分位,开启后每进千加逗号分隔
- 参数三 动画间隔,默认500
- 参数四 动画粒度,默认100
此方法会智能过滤除数字外的字符,如果动态了修改了数字应该加$('#xx').data('num', '');
重置一下。
4.3.经纬度转换
快速使用:
// GCJ02转BD09
var point = admin.util.Convert_GCJ02_To_BD09({lat: 30.505674, lng: 114.40043});
console.log(point.lng + ',' + point.lat);// BD09转GCJ02
var point = admin.util.Convert_BD09_To_GCJ02({lat: 30.512004, lng: 114.405701});
console.log(point.lng + ',' + point.lat);
- 高德地图、腾讯地图以及谷歌中国区地图使用的是GCJ-02坐标系
- 百度地图使用的是BD-09坐标系
不同的坐标系之间会有几十到几百米的偏移,所以在开发基于地图的产品时,可以通过此方法修正不同坐标系之间的偏差, 详细了解国内各坐标系。
4.4.深度克隆对象
var o1 = {name: 'xxx', role: ['admin', 'user']};var o2 = admin.util.deepClone(o1);
对象型在参数传递时通常是引用传递,有时需要把对象克隆一份再传递,避免传递的参数被修改导致第二次传递出现问题。
4.5.判断富文本是否为空
admin.util.fullTextIsEmpty('<p><span>哈哈</span><img src="xxx.jpg"/>');
判断规则,有文字,有img、audio、video、iframe等标签都属于不为空。
4.6.移除指定style
<div style="color: red;background-color: green;">Hello</div>
像上面这样有多个内联样式style,如何只移除其中一个或多个呢:
admin.util.removeStyle('background-color');admin.util.removeStyle(['background-color', 'color']);
4.7.模板引擎
var html = admin.util.tpl('<p>{{d.name}}</p>', {name: 'xxx'}, '{{', '}}');
- 参数一 模板内容
- 参数二 填充数据
- 参数三 非必填,边界符,默认
{{
- 参数四 非必填,边界符,默认
}}
它与laytpl使用方式一致,并且解决了laytpl对js注释支持不友好,laytpl模板中有js注释会导致最后渲染的内容有问题。
加载独立页面:
<div id="demo1"></div>
<script>layui.use(['layer', 'admin'], function () {var $ = layui.jquery;var admin = layui.admin;admin.ajax({url: 'xxx.html', dataType: 'html', success: function (html) {$('#demo1').html(admin.util.tpl(html, {name: 'xxx'}));}});});
</script>
独立页面xxx.html
:
<div>{{name}}</div>
<script>layui.use(['layer'], function () {// 我可以加注释哦,laytpl不可以哦layui.layer.msg('Hello 我被加载了');});
</script>
4.8.滚动到顶部
admin.util.scrollTop(); // 主体部分滚动到顶部admin.util.scrollTop('html,body'); // 自定义元素滚动到顶部admin.util.scrollTop('#xxDiv'); // 自定义元素滚动到顶部
由于spa版本多标签和单标签的滚动条所在元素都不一样,而且也不在body上, 所以封装了scrollTop方法可自动判断主体部分滚动条所在的元素。
4.9.事件监听
监听侧边栏折叠/展开:
admin.on('flexible', function (d) {setTimeout(function () {myCharts1.resize();}, 360);
});
一般用于更新echarts尺寸等,要延迟360毫秒再更新,因为折叠展开有个过渡效果。
监听页面被卸载:
admin.on('destroy(plugin/other/editor)', function () {tinymce.get('demoEditor').destroy(false);
});
括号里面是页面的路径地址,没有#号,可用于销毁定时器、组件等。
监听页面进入前台:
layui.admin.on('show(console/console)', function () {myCharts1.resize();
});
括号里面是页面的路径地址,没有#号,一般用于更新echarts尺寸等,比如打开了两个标签页, 缩放屏幕大小再进入另一个标签页,echarts尺寸不会自动变化,可以监听页面进入前台并更新尺寸。
其他事件监听:
/* 监听tab切换事件 */
admin.on('tab', function (d) {// d.layId表示当前tab的url
});// 监听tab关闭事件
admin.on('tabDelete', function (d) {// d.layId表示当前tab的url
});/* 监听多系统切换事件 */
admin.on('nav', function (d) {// d.navId表示当前多系统的navId
});
实现刷新页面记忆折叠状态,在main.js增加:
admin.on('flexible', function (d) {admin.putTempData('nav-expand', d.expand);
});var expand = admin.getTempData('nav-expand');
if (expand !== undefined) admin.flexible(expand);
4.10.动态模板
直接赋值数据:
<script type="text/html" ew-tpl="['a','b','c']" data-done="layui.form.render()"><div>{{# layui.each(d,function(i,item){ }}<div>{{item}}</div>{{# }); }}</div>
</script>
<!-- 也可以引用变量 -->
<script id="userListTpl" type="text/html" ew-tpl="userList"><div>{{# if(d){ }} <!-- 这里判断以下因为可能值还没定义 -->{{# layui.each(d,function(i,item){ }}<div>{{item}}</div>{{# }); }}{{# } }}</div>
</script>
<script>layui.use(['admin'], function() {window.userList = ['a', 'b', 'c'];// admin模块一加载会自动渲染,但userList还未定义,所以定义完要重新渲染admin.renderTpl('#userListTpl');});
</script>
使用远程数据,注意要加引号'user.json'
:
<script type="text/html" ew-tpl="'user.json'" data-method="post" data-where="{sex:'女'}" data-headers="{token: 'xxx'}"><div>{{# layui.each(d.data,function(i,item){ }}<div>{{item.username}}</div>{{# }); }}</div>
</script>
通过ew-tpl
来表示这是一个动态模板以及设置数据源,通过data-xxx
配置其他参数:
- done 渲染完成后的回调
- url 远程数据的url
- method 远程数据的请求方式
- where 远程数据的请求条件,也可以
data-where="JSON.stringify({})"
- headers 远程数据的请求header
- content-type 如
data-content-type="application/json;charset=UTF-8"
注意远程数据url一定要加引号,加引号的好处你还可以这样使用:
ew-tpl=" layui.setter.baseServer + '/user.json' "
动态模板会在页面加载后自动渲染,如果要重新渲染:
admin.renderTpl('#userListTpl'); // 参数为模板的jquery选择器
使用例子,比如用户管理的搜索里面的性别下拉换成动态的:
<!-- 表格工具栏 -->
<form class="layui-form toolbar"><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">性 别:</label><script type="text/html" ew-tpl="'../../json/sex.json'" data-done="layui.form.render('select');"><div class="layui-input-inline"><select name="sex"><option value="">选择性别</option>{{# layui.each(d.data,function(i,item){ }}<option value="{{item.value}}">{{item.name}}</option>{{# }); }}</select></div></script></div></div>
</form>
<!-- 数据表格 -->
<table id="userTable" lay-filter="userTable"></table>
sex.json数据:
{"code": 200, "data": [{"name": "男", "value": 0}, {"name": "女", "value": 1}]}
注意这里有个小细节,select上面还有一个div,对于select的动态模板,建议select外面最好多一层,因为select会被layui美化, 外面不加一层当重新渲染模板的时候不能把layui美化的旧的select移除,另外ew-tpl="'sex.json'"
这里先是双引号再是单引号,不要漏掉了。
5.1.公共类
类名(class) | 说明 |
---|---|
pull-left | 左浮动 |
pull-right | 右浮动 |
text-left | 内容居左 |
text-center | 内容居中 |
text-right | 内容居右 |
inline-block | 设置display为inline-block |
bg-white | 设置背景为白色 |
layui-link | 设置a标签颜色为主题色 |
layui-text | .layui-text下面的a标签为蓝色 |
text-muted | 文字颜色为灰色 |
text-success | 文字颜色为绿色,成功色 |
text-warning | 文字颜色为黄色警告色 |
text-danger | 文字颜色为红色危险色 |
text-info | 文字颜色为蓝色信息色 |
text-primary | 文字颜色为主题色 |
以上是easyweb增加的公共类,当然也可以使用Layui公共类。
5.2.组件样式
类名(class) | 说明 |
---|---|
icon-btn | 带图标的按钮,会缩小边距 |
icon-date | 在元素的右边加入日期的图标 |
icon-search | 在元素的右边加入搜索的图标 |
btn-circle | 圆形按钮,参见便签界面 |
arrow2 | 设置侧边栏小三角为箭头图标,加在layui-nav上 |
arrow3 | 设置侧边栏小三角为加减号图标,加在layui-nav上 |
close-footer | 关闭页脚,加在body上 |
hide-body-title | 全局隐藏单标签模式标题栏,加在body上 |
table-tool-mini | 数据表格工具栏mini样式,加在table父元素上 |
full-table | 针对full-xxx的table的工具栏mini样式 |
mini-bar | 如果有滚动条,使用细的风格 |
layui-form-select-top | 控制下拉框上弹出,加载select父元素上 |
ew-tb-cell-ck | 数据表格里面checkbox |
ew-field-group | easyweb的字段集辅助类 |
<!-- 图标按钮 -->
<button class="layui-btn icon-btn"><i class="layui-icon"></i>搜索</button><!-- 日期图标 -->
<input class="layui-input icon-date" type="text"/>
<!-- 搜索图标 -->
<input class="layui-input icon-search" type="text"/><!-- 圆形按钮 -->
<div class="btn-circle"><i class="layui-icon layui-icon-add-1"></i>
</div><!-- 下拉框上弹出 -->
<div class="layui-form-select-top"><select>....</select>
</div><!-- 关闭页脚 -->
<body class="layui-layout-body close-footer"><!-- 表格工具栏mini样式 -->
<div class="table-tool-mini full-table"><table id="xxTable" lay-filter="xxTable"></table>
</div><!-- 字段集嵌套数据表格 -->
<div class="ew-field-group"><fieldset class="layui-elem-field"><legend>我是标题</legend></fieldset><div class="ew-field-box"><table id="demoFieldTb" lay-filter="demoFieldTb"></table></div>
</div>
5.3.表单弹窗
类名(class) | 说明 |
---|---|
model-form | 调整弹窗内的表单的间距使之更好看 |
model-form-body | 表单内容部分,高度自适应,超过屏幕高度显示滚动条 |
model-form-footer | 表单底部按钮部分,用于固定底部按钮 |
layui-form-required | 表单必填项加红色星号 |
表单弹窗示例:
<script type="text/html" id="modelUser"><form id="modelUserForm" lay-filter="modelUserForm" class="layui-form model-form"><input name="userId" type="hidden"/><div class="layui-form-item"><label class="layui-form-label layui-form-required">账号</label><div class="layui-input-block"><input name="username" placeholder="请输入账号" class="layui-input"/></div></div><div class="layui-form-item text-right"><button class="layui-btn layui-btn-primary" type="button" ew-event="closePageDialog">取消</button><button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button></div></form>
</script>
<script>layui.use(['admin'],function(){var admin = layui.admin;admin.open({type: 1,title: '添加用户',content: $('#modelUser').html(),success: function (layero, dIndex) {// 表单的操作,事件绑定等都写在success回调里面}});});
</script>
固定底部操作按钮示例:
<script type="text/html" id="modelUser"><form class="layui-form model-form no-padding" id="modelUserForm" lay-filter="modelUserForm"><div class="model-form-body" style="max-height: 320px;"> <!-- 如果要超出屏幕才固定底部,不要写max-height --><div class="layui-form-item"><label class="layui-form-label">实习公司</label><div class="layui-input-block"><input name="companyName" class="layui-input"/></div></div><!-- ......省略 --></div><div class="layui-form-item text-right model-form-footer"><button class="layui-btn layui-btn-primary" type="button" ew-event="closePageDialog">取消</button><button class="layui-btn" lay-filter="modelSubmitUser" lay-submit>保存</button></div></form>
</script>
固定底部按钮需要model-form-body和model-form-footer,普通表单弹窗只需要model-form
5.4.表格工具栏
类名(class) | 说明 |
---|---|
toolbar | 调整表格上面的表单间距使之更好看 |
w-auto | 设置width:auto,用于重置一些有固定宽度表单元素 |
mr0 | 设置margin-right:0,用于重置一些表单元素的样式 |
form-search-show-expand | 点击了展开才显示出来 |
form-search-expand | 表格搜索栏展开\折叠按钮默认样式 |
<!-- 表格顶部工具栏区域 -->
<div class="layui-form toolbar"><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label w-auto">账 号:</label><div class="layui-input-inline mr0"><input name="username" class="layui-input" type="text" placeholder="输入账号"/></div></div><!-- 加了form-search-show-expand类在展开的时候才显示 --><div class="layui-inline form-search-show-expand"><label class="layui-form-label w-auto">用户名:</label><div class="layui-input-inline mr0"><input name="nickName" class="layui-input" type="text" placeholder="输入用户名"/></div></div><div class="layui-inline"><button class="layui-btn icon-btn" lay-filter="formSubSearchUser" lay-submit><i class="layui-icon"></i>搜索</button><!-- 添加这个按钮可展开/折叠表单 --><a class="layui-btn form-search-expand" search-expand>展开 <i class="layui-icon layui-icon-down"></i></a></div></div>
</div><!-- 表格 -->
<table id="tableUser" lay-filter="tableUser"></table>
移动端自动适配效果:
表格搜索折叠/展开事件监听:
<!-- 直接写js -->
<a class="layui-btn" search-expand="d.expand?layer.msg('展开了'):layer.msg('折叠了')">展开 <i class="layui-icon layui-icon-down"></i>
</a><!-- 调用方法 -->
<a class="layui-btn" search-expand="onExpandChange(d)"></a>
<script>layui.use(['layer'], function () {window.onExpandChange = function(d){console.log(d); // d包含d.expand,d.elem}});
</script>
5.5.垂直选项卡
只需要在layui-tab的基础上多加一个layui-tab-vertical
类即可实现:
<div class="layui-tab layui-tab-vertical"><ul class="layui-tab-title"><li class="layui-this">系统管理</li><li>用户管理</li><li>权限分配</li></ul><div class="layui-tab-content"><div class="layui-tab-item layui-show">内容1</div><div class="layui-tab-item">内容2</div><div class="layui-tab-item">内容3</div></div>
</div>
如果要修改选项卡标题的宽度:
<!-- title和content两处地方都需要修改 -->
<div class="layui-tab layui-tab-vertical"><ul class="layui-tab-title" style="width: 200px;">......省略</ul><div class="layui-tab-content" style="margin-left: 200px;">......省略</div>
</div>
如果要选项卡的标题在右侧,再多加一个layui-tab-vertical-right
类即可:
<div class="layui-tab layui-tab-vertical layui-tab-vertical-right"><ul class="layui-tab-title" style="width: 200px;">......省略</ul><div class="layui-tab-content" style="margin-right: 200px;">......省略</div>
</div>
选项卡的灰色分隔线的高度是标题区域的高度,如果当内容高度高于标题区域高度时想要分隔线的高度最大:
<!-- 多加一个`layui-tab-vertical-full`类就可以了 -->
<div class="layui-tab layui-tab-vertical layui-tab-vertical-full"><ul class="layui-tab-title">......省略</ul><div class="layui-tab-content">......省略</div>
</div>
垂直选项卡中使用栅格布局样式错位,在layui-row上加一些样式:
<div class="layui-tab layui-tab-vertical"><ul class="layui-tab-title"><li class="layui-this">系统管理</li><li>用户管理</li></ul><div class="layui-tab-content"><div class="layui-tab-item layui-show">内容1</div><div class="layui-tab-item"><div class="layui-row" style="float: left;width: 100%;"><div class="layui-col-md6">内容2</div><div class="layui-col-md6">内容使用栅格</div></div></div></div>
</div>
5.6.徽章扩展
<span class="layui-badge layui-badge-green">绿色</span>
<span class="layui-badge layui-badge-blue">蓝色</span>
<span class="layui-badge layui-badge-red">红色</span>
<span class="layui-badge layui-badge-yellow">黄色</span>
<span class="layui-badge layui-badge-gray">灰色</span>
用layui-badge-list
包裹,会有更好的间距和尺寸:
<div class="layui-badge-list"><span class="layui-badge layui-badge-gray">很有想法的</span><span class="layui-badge layui-badge-gray">专注设计</span><span class="layui-badge layui-badge-gray">辣~</span><span class="layui-badge layui-badge-gray">大长腿</span><span class="layui-badge layui-badge-gray">川妹子</span><span class="layui-badge layui-badge-gray">海纳百川</span>
</div>
5.7.下拉树单选
<div id="demoSel" class="ew-xmselect-tree"></div>
xmSelect下拉单选树增加一个ew-xmselect-tree
可以有更好的样式。
5.8.fixed方式select
只需要在select的父元素上面增加class ew-select-fixed
即可:
<div style="height: 80px;overflow: auto;" onscroll="layui.admin.hideFixedEl();"><div class="ew-select-fixed"><select name="ptTypeId"><option value="">请选择</option><option value="1">选项一</option><option value="2">选项二</option></select></div>
</div>
fixed定位的select用在数据表格中不需要对表格做任何修改就可以显示出来,还可以用在带有滚动表的容器中,比如一个很长的表单弹窗, 一定高度后显示滚动条,里面select是无法越出滚动条容器显示的,使用fixed方式的select即可超出容器的滚动条显示, 使用了fixed定位后外层容器滚动select不会跟随滚动,可在容器上添加滚动时收起select。
6.1.1.快速使用
<!-- click模式触发 -->
<div class="dropdown-menu"><button class="layui-btn icon-btn"> Click me <i class="layui-icon layui-icon-drop"></i></button><ul class="dropdown-menu-nav"><li><a>1st menu item</a></li><li><a>2nd menu item</a></li><li><a>3rd menu item</a></li></ul>
</div>
<!-- hover模式触发,增加dropdown-hover即可 -->
<div class="dropdown-menu dropdown-hover"><button class="layui-btn icon-btn"> Hover me <i class="layui-icon layui-icon-drop"></i></button><ul class="dropdown-menu-nav"><li><a>1st menu item</a></li><li><a>2nd menu item</a></li><li><a>3rd menu item</a></li></ul>
</div>
<script>layui.use(['dropdown'], function () {var dropdown = layui.dropdown; // 加载模块});
</script>
6.1.2.更多样式
<!-- 标题及禁用样式 -->
<div class="dropdown-menu dropdown-hover"><button class="layui-btn icon-btn"> 更多样式 <i class="layui-icon layui-icon-drop"></i></button><ul class="dropdown-menu-nav"><li class="title">HEADER</li><li><a><i class="layui-icon layui-icon-star-fill"></i>1st menu item</a></li><li class="disabled"><a><i class="layui-icon layui-icon-template-1"></i>2nd menu item</a></li><hr><li class="title">HEADER</li><li><a><i class="layui-icon layui-icon-set-fill"></i>3rd menu item</a></li></ul>
</div><!-- 带小三角样式 -->
<div class="dropdown-menu dropdown-hover"><button class="layui-btn icon-btn"> 带小三角 <i class="layui-icon layui-icon-drop"></i></button><ul class="dropdown-menu-nav"><div class="dropdown-anchor"></div><!-- 多加一个这个即可 --><li><a>1st menu item</a></li><li><a>2nd menu item</a></li><li><a>3rd menu item</a></li></ul>
</div><!-- 暗色主题 -->
<div class="dropdown-menu"><button class="layui-btn layui-btn-normal icon-btn"> 暗色主题 <i class="layui-icon layui-icon-drop"></i></button><ul class="dropdown-menu-nav dark"><!-- 加一个dark即可 --><div class="dropdown-anchor"></div><li class="title">HEADER</li><li><a><i class="layui-icon layui-icon-star-fill"></i>1st menu item</a></li><li class="disabled"><a><i class="layui-icon layui-icon-template-1"></i>2nd menu item</a></li><hr><li class="title">HEADER</li><li><a><i class="layui-icon layui-icon-set-fill"></i>3rd menu item</a></li></ul>
</div>
6.1.3.对任意元素使用
<div class="dropdown-menu dropdown-hover"><input type="text" placeholder="一个会跳舞的输入框" class="layui-input"/><ul class="dropdown-menu-nav"><li class="title">是不是在找</li><li><a>另一个会跳舞的下拉框</a></li><li><a>一杯忧郁的可乐</a></li></ul>
</div>
6.1.4.带遮罩层
遮罩层是分离式的绑定,通过data-dropdown绑定:
<button class="layui-btn layui-btn-normal icon-btn" data-dropdown="#dropdown1">带遮罩层 <i class="layui-icon layui-icon-drop"></i>
</button><!-- 下拉菜单 -->
<ul class="dropdown-menu-nav dropdown-bottom-right layui-hide" id="dropdown1"><div class="dropdown-anchor"></div><li class="title">HEADER</li><li><a><i class="layui-icon layui-icon-star-fill"></i>1st menu item</a></li><li class="disabled"><a><i class="layui-icon layui-icon-template-1"></i>2nd menu item</a></li><hr><li class="title">HEADER</li><li><a><i class="layui-icon layui-icon-set-fill"></i>3rd menu item</a></li>
</ul>
6.1.5.自定义下拉内容
<div class="dropdown-menu"><button class="layui-btn layui-btn-normal icon-btn"> 克隆/下载 <i class="layui-icon layui-icon-drop"></i></button><div class="dropdown-menu-nav dropdown-bottom-right" style="width: 280px;padding: 0 10px 10px 10px;"><div class="dropdown-anchor"></div><!-- 下面是自定义内容 --><div class="layui-tab layui-tab-brief"><ul class="layui-tab-title"><li class="layui-this">HTTPS</li><li>SSH</li></ul><div class="layui-tab-content" style="padding: 10px 0 10px 0;"><div class="layui-tab-item layui-show"><input class="layui-input" value="https://gitee.com/whvse/easyweb-jwt.git"/></div><div class="layui-tab-item"><input class="layui-input" value="git@gitee.com:whvse/easyweb-jwt.git"/></div></div></div><button class="layui-btn layui-btn-sm layui-btn-fluid" style="margin-bottom: 10px;">Download ZIP</button><img src="http://p1.music.126.net/voV3yPduAhNATICMRJza1A==/109951164017919367.jpg" width="100%"><!-- //end.自定义内容结束 --></div>
</div>
6.1.6.控制显示方向
在dropdown-menu-nav上加下面的class可控制位置:
类名 | 位置 |
---|---|
dropdown-bottom-left | 下左弹出 |
dropdown-bottom-center | 下中弹出 |
dropdown-bottom-right | 下右弹出 |
dropdown-top-left | 上左弹出 |
dropdown-top-center | 上中弹出 |
dropdown-top-right | 上右弹出 |
dropdown-left-top | 左上弹出 |
dropdown-left-center | 左中弹出 |
dropdown-left-bottom | 左下弹出 |
dropdown-right-top | 右上弹出 |
dropdown-right-center | 右中弹出 |
dropdown-right-bottom | 右下弹出 |
<!-- Bottom Center -->
<div class="dropdown-menu dropdown-hover"><button class="layui-btn layui-btn-primary icon-btn">Bottom <i class="layui-icon layui-icon-drop"></i> Center</button><ul class="dropdown-menu-nav dropdown-bottom-center"><!-- 这里加控制方向的类 --><div class="dropdown-anchor"></div><li><a>1st menu item</a></li><li><a>2nd menu item</a></li><li><a>3rd menu item</a></li></ul>
</div><!-- Bottom Right -->
<div class="dropdown-menu dropdown-hover"><button class="layui-btn layui-btn-primary icon-btn">Bottom Right <i class="layui-icon layui-icon-drop"></i></button><ul class="dropdown-menu-nav dropdown-bottom-right"><!-- 这里加控制方向的类 --><div class="dropdown-anchor"></div><li><a>1st menu item</a></li><li><a>2nd menu item</a></li><li><a>3rd menu item</a></li></ul>
</div>
6.1.7.在数据表格中使用
数据表格中使用分离式的绑定,并且加no-shade="true"
去掉遮罩层:
<!-- 表格操作列 -->
<script type="text/html" id="tableBar"><a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="edit">修改</a><a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a><!-- 下拉菜单 --><a class="layui-btn layui-btn-xs" data-dropdown="#dropUser{{d.LAY_INDEX}}" no-shade="true">更多<i class="layui-icon layui-icon-drop" style="font-size: 12px;margin-right: 0;"></i></a><ul class="dropdown-menu-nav dropdown-bottom-right layui-hide" id="dropUser{{d.LAY_INDEX}}"><div class="dropdown-anchor"></div><li><a lay-event="edit2"><i class="layui-icon layui-icon-edit"></i>修改用户</a></li><li><a lay-event="del2"><i class="layui-icon layui-icon-delete"></i>删除用户</a></li><li><a lay-event="lock2"><i class="layui-icon layui-icon-password"></i>锁定用户</a></li></ul>
</script>
<script>layui.use(['table', 'dropdown'], function () {var table = layui.table;table.render({cols: [[{field: 'username', title: '账号'},{toolbar: '#tableBar', title: '操作'}]]});});</script>
6.1.8.气泡确认框
<!-- 下弹出 -->
<div class="dropdown-menu"><button class="layui-btn layui-btn-primary icon-btn"> 气泡确认框 <i class="layui-icon layui-icon-drop"></i></button><div class="dropdown-menu-nav dropdown-popconfirm"><div class="dropdown-anchor"></div><div class="dropdown-popconfirm-title"><i class="layui-icon layui-icon-help"></i>这是一段内容确定删除吗?</div><div class="dropdown-popconfirm-btn"><button class="layui-btn" btn-cancel>取消</button><button class="layui-btn layui-btn-normal">确定</button></div></div>
</div>
<!-- 上弹出 -->
<div class="dropdown-menu"><button class="layui-btn layui-btn-primary icon-btn"> 气泡确认框 <i class="layui-icon layui-icon-drop"></i></button><div class="dropdown-menu-nav dropdown-popconfirm dropdown-top-right"><div class="dropdown-anchor"></div><div class="dropdown-popconfirm-title"><i class="layui-icon layui-icon-about"></i>这是一段内容确定删除吗?</div><div class="dropdown-popconfirm-btn"><button class="layui-btn" btn-cancel>取消</button><button class="layui-btn layui-btn-normal">确定</button></div></div>
</div>
6.2.1.快速使用
layui.use(['notice'], function(){var notice = layui.notice;// 消息通知notice.success({title: '消息通知',message: '你有新的消息,请注意查收!'});// 提示框,1成功、2失败、3警告、4加载、5信息(蓝色图标)notice.msg('Hello', {icon: 1});
});
6.2.2.全部方法
方法 | 参数 | 说明 |
---|---|---|
success(object) | 见下方 | 成功消息(绿色) |
warning(object) | 见下方 | 警告消息(黄色) |
error(object) | 见下方 | 错误消息(红色) |
info(object) | 见下方 | 通知消息(蓝色) |
show(object) | 见下方 | 自定义样式 |
msg(string, object) | 文本,其他参数 | 提示框 |
destroy() | 无 | 关闭全部 |
hide(object, toast, closedBy) | 见下方 | 关闭指定的通知 |
settings(object) | 见下方 | 统一设置默认值 |
统一设置默认值:
notice.settings({timeout: 1500,transitionIn: 'flipInX',onOpened: function(){console.log('notice opend!');}
});
关闭指定的通知:
notice.hide({}, document.querySelector('.toast'));
- 参数一 重写一些参数,比如关闭动画等
- 参数二 根据自定义的className选择关闭的对象
6.2.3.参数列表
参数 | 说明 | 默认值 | 可选值 |
---|---|---|---|
title | 标题 | 无 | string类型 |
message | 内容 | 无 | string类型 |
position | 显示位置 | topRight | 见下方 |
transitionIn | 进入动画 | fadeInLeft | 见下方 |
transitionOut | 退出动画 | fadeOutRight | 见下方 |
timeout | 消失时间 | 5000 | 单位毫秒,false永不消失 |
progressBar | 进度条 | true | true显示、false不显示 |
balloon | 气泡效果 | false | true开启、false关闭 |
close | 关闭按钮 | true | true显示,false不显示 |
pauseOnHover | 鼠标滑过暂停消失时间 | true | true、false |
resetOnHover | 鼠标滑过重置消失时间 | false | true、false |
animateInside | 文字动画效果 | false | true开启、false关闭 |
className | 自定义class | 无 | 多个用空格分隔 |
theme | 主题 | light | light、dark |
audio | 音效 | 无 | 1,2,3,4,5,6 |
image | 显示图片 | 无 | 图片地址 |
imageWidth | 图片宽度 | 60 | 数字 |
buttons | 显示按钮 | [] | [ [ 'btn1', function(){} ], ['btn2', function(){} ] ] |
overlay | 遮罩层 | false | true显示,false不显示 |
drag | 滑动关闭 | true | true开启,false关闭 |
layout | 布局类型 | 2 | 1标题和内容并排,2两排显示 |
rtl | 布局方向 | false | false内容居左,true居右 |
displayMode | 显示模式 | 0 | 0无限制,1同类型存在不显示,2同类型存在先移除 |
targetFirst | 插入方式 | 自动 | true从上插入,false下插入 |
onOpened | 打开后回调函数 | 无 | function |
onClosed | 关闭后回调函数 | 无 | function |
titleColor | 标题颜色 | 默认 | 颜色单位 |
titleSize | 标题大小 | 默认 | 尺寸单位 |
messageColor | 文字颜色 | 默认 | 颜色单位 |
messageSize | 文字大小 | 默认 | 尺寸单位 |
backgroundColor | 背景颜色 | 默认 | 颜色单位 |
progressBarColor | 进度条颜色 | 默认 | 颜色单位 |
maxWidth | 最大宽度 | 空 | 尺寸单位 |
参数position显示位置可选值:
属性 | 说明 |
---|---|
bottomRight | 右下角 |
bottomLeft | 左下角 |
topRight | 右上角 |
topLeft | 左上角 |
topCenter | 顶部中间 |
bottomCenter | 底部中间 |
center | 正中间 |
参数transitionIn进入动画可选值:
属性 | 说明 |
---|---|
bounceInLeft | 向左反弹 |
bounceInRight | 向右反弹 |
bounceInUp | 向上反弹 |
bounceInDown | 向下反弹 |
fadeIn | 淡入 |
fadeInDown | 向下淡入 |
fadeInUp | 向上淡入 |
fadeInLeft | 向左淡入 |
fadeInRight | 向右淡入 |
flipInX | 翻转进入 |
参数transitionOut退出动画可选值:
属性 | 说明 |
---|---|
fadeOut | 淡出 |
fadeOutUp | 向上淡出 |
fadeOutDown | 向下淡出 |
fadeOutLeft | 向左淡出 |
fadeOutRight | 向右淡出 |
flipOutX | 翻转退出 |
6.2.4.解决弹窗遮挡
<!-- 页面加入样式 -->
<style>body .iziToast-overlay {z-index: 19892001;}body .iziToast-wrapper {z-index: 19892002;}
</style>
6.3.1.快速使用
<input id="demoCascader1" placeholder="请选择" class="layui-hide"/><script>
layui.use(['cascader'], function () {var $ = layui.jquery;var cascader = layui.cascader;cascader.render({elem: '#demoCascader1',data: [{value: 'beijing',label: '北京',children: [{value: 'gugong',label: '故宫'},{value: 'tiantan',label: '天坛'},{value: 'wangfujing',label: '王府井'}]}]});// 请求远程数据cascader.render({elem: '#demoCascader1',reqData: function (values, callback, data) {$.get('xxxx.json', function(res){callback(res.data); // 数据请求完成通过callback回调},'json');}});// 处理数据格式,如果你的数据没有value、label字段可以前端处理cascader.render({elem: '#demoCascader1',reqData: function (values, callback, data) {$.get('xxxx.json', function(res){function each(data) {for (var i = 0; i < data.length; i++) {data[i].value = data[i].id;data[i].label = data[i].name;if (data[i].children) {each(data[i].children);}}}each(res.data);callback(res.data);},'json');}});// 如果你的数据不是children形式,可以前端转换cascader.render({elem: '#demoCascader1',reqData: function (values, callback, data) {$.get('xxxx.json', function(res){callback(pidToChildren(res.data, 'id', 'pid', 0));},'json');}});/* pid转children形式 */function pidToChildren(data, idName, pidName, childName, pId) {if (!childName) childName = 'children';var newList = [];for (var i = 0; i < data.length; i++) {if (data[i][idName] == data[i][pidName]) return;if (pId === undefined) pId = 0;if (data[i][pidName] == pId) {var children = pidToChildren(data, idName, pidName, childName, data[i][idName]);if (children.length > 0) data[i][childName] = children;newList.push(data[i]);}}return newList;}});
</script>
6.3.2.异步加载
<input id="demoCascader1" placeholder="请选择" class="layui-hide"/><script>
layui.use(['cascader'], function () {var $ = layui.jquery;var cascader = layui.cascader;cascader.render({elem: '#demoCascader1',reqData: function (values, callback, data) {// values是当前所有选中的值,data是当前选中的对象$.get('xxxx.json', { id: data.value }, function(res){callback(res.data); // 数据请求完成通过callback回调},'json');}});
});
</script>
异步加载的数据格式为:
[{value: 'beijing', label: '北京', haveChildren: true},{value: 'jiangsu', label: '江苏', haveChildren: true}
]
通过haveChildren字段来标识是否还有子节点,如果你的后台数据格式不是这样,可以在callback之前格式化:
cascader.render({elem: '#demoCascader1',reqData: function (values, callback, data) {// values是当前所有选中的值,data是当前选中的对象$.get('xxxx.json', { id: data.value }, function(res){var newList = [];for(var i=0;i<res.data.length;i++){var item = res.data[i];newList.push({value: item.id,label: item.name,haveChildren: item.haveChildren});}callback(newList); // 数据请求完成通过callback回调},'json');}
});
6.3.3.自定义分隔符
<input id="demoCascader1" placeholder="请选择" class="layui-hide"/><script>
layui.use(['cascader'], function () {var $ = layui.jquery;var cascader = layui.cascader;cascader.render({elem: '#demoCascader1',data: [],renderFormat: function (labels, values) {return labels.join(' / '); // 默认是用斜杠分割,可以自定义}});
});
</script>
6.3.4.搜索功能
<input id="demoCascader1" placeholder="请选择" class="layui-hide"/><script>
layui.use(['cascader'], function () {var $ = layui.jquery;var cascader = layui.cascader;cascader.render({elem: '#demoCascader1',data: [],filterable: true // 这个参数是开启搜索功能});// 自定义搜索cascader.render({elem: '#demoCascader1',data: [],filterable: true,reqSearch: function (keyword, callback, dataList) {// keyword是搜索的关键字,dataList是当前的全部数据集合$.get('xxx.json', { keyword: keyword }, function(res){callback(res);},'json')}});
});
</script>
搜索后端接口返回的数据格式为:
[ {"value": "1,2", "label": "北京 / 王府井"},{"value": "1,3", "label": "北京 / 故宫"}
]
如果要标记关键字为红色:<span class=\"search-keyword\">北京</span> / 王府井
6.3.5.省市区选择
<input id="demoCascader1" placeholder="请选择" class="layui-hide"/><script type="text/javascript" src="/assets/module/cascader/citys-data.js"></script>
<script>
layui.use(['cascader'], function () {var $ = layui.jquery;var cascader = layui.cascader;cascader.render({elem: '#demoCascader1',data: citysData,itemHeight: '250px',filterable: true});
});
</script>
省市区的数据已经封装好了,只需要引入数据的js即可,数据包含省市区,value是区号, 如果需要对数据进行处理,cascader封装了几种处理数据方法:
// value也是中文而不是区号
var data = cascader.getCityData(admin.util.deepClone(citysData));
cascader.render({elem: '#demoCascader11',data: data
});// 只显示省市,不要区域
var data = cascader.getCity(admin.util.deepClone(citysData));// 只显示省份,不要市区
var data = cascader.getProvince(admin.util.deepClone(citysData));// 只显示身份,并且value是中文,而不是区号
var data = cascader.getCityData(cascader.getProvince(admin.util.deepClone(citysData)));
6.3.6.全部方法
<input id="demoCascader1" placeholder="请选择" class="layui-hide"/><script>
layui.use(['cascader'], function () {var $ = layui.jquery;var cascader = layui.cascader;var ins1 = cascader.render({elem: '#demoCascader1',data: []});ins1.data; // 获取当前的数据ins1.open(); // 展开ins1.hide(); // 关闭ins1.removeLoading(); // 移除加载中的状态ins1.setDisabled(true); // 禁用或取消禁用ins1.getValue(); // 获取选中的数据值ins1.getLabel(); // 选取选中的数据名称ins1.setValue('1,2'); // 设置值});
</script>
6.3.7.全部参数
参数名称 | 介绍 | 默认值 |
---|---|---|
elem | 需要渲染的元素 | |
data | 数据 | |
clearable | 是否开启清除 | true |
clearAllActive | 清除时清除所有列选中 | false |
trigger | 次级菜单触发方式,可选'hover' | 'click' |
disabled | 是否禁用 | false |
changeOnSelect | 是否点击每一项都改变值 | false |
filterable | 是否开启搜索功能 | false |
notFoundText | 搜索为空是提示文字 | '没有匹配数据' |
itemHeight | 下拉列表的高度 | '180px' |
reqData(values, callback, data) | 异步获取数据的方法 | |
reqSearch(keyword, callback, dataList) | 自定义搜索的方法 | |
renderFormat(labels, values) | 选择后用于展示的函数 | |
onChange(values, data) | 数据选择改变的回调 | |
onVisibleChange(isShow) | 展开和关闭的回调 |
6.4.2.全部参数
参数 | 说明 | 默认值 |
---|---|---|
defaultText | 提示文字 | +请输入 |
skin | 样式风格 | |
removeWithBackspace | 回退键可删除已添加的标签 | false |
focusWithClick | 点击已添加标签输入框获取焦点 | true |
autocomplete_url | 自动提示接口url | |
autocomplete | 接口配置 |
autocomplete参数:
$('#demoTagsInput').tagsInput({autocomplete_url: '../../json/tagsInput.json',autocomplete: {type: 'post',data: {access_token: 'xxxxx'}}
});
type是请求方式,默认是get请求,data是额外参数,请求autocomplete_url会传递name
参数(输入框的值)。
更详细的使用文档可以参考jQuery-Tags-Input。
此插件基于 jQuery-Tags-Input 二次修改。
6.5.1.快速使用
<div class="split-group"><div class="split-item" id="demoSplit1">面板一</div><div class="split-item" id="demoSplit2">面板二</div>
</div><script>layui.use(['Split'], function () {var $ = layui.jquery;var Split = layui.Split;// 水平分割,需要分割的元素(id)、默认大小(百分比)、最小值(单位px)Split(['#demoSplit1', '#demoSplit2'], {sizes: [25, 75], minSize: 100});});
</script>
6.5.2.垂直分割
<div class="split-group-vertical"><div class="split-item" id="demoSplit3">面板一</div><div class="split-item" id="demoSplit4">面板二</div>
</div><script>layui.use(['Split'], function () {var $ = layui.jquery;var Split = layui.Split;// 垂直分割Split(['#demoSplit3', '#demoSplit4'], {direction: 'vertical'});});
</script>
6.5.3.嵌套使用
<div class="split-group" style="height: 600px;"><div class="split-item" id="demoSplit8"><div class="split-group-vertical"><div class="split-item" id="demoSplit10">面板一</div><div class="split-item" id="demoSplit11">面板二</div></div></div><div class="split-item" id="demoSplit9">面板三</div>
</div><script>layui.use([Split'], function () {var $ = layui.jquery;var Split = layui.Split;// 垂直水平分割Split(['#demoSplit8', '#demoSplit9'], {sizes: [25, 75], minSize: 100});Split(['#demoSplit10', '#demoSplit11'], {direction: 'vertical'});});
</script>
6.6.1.快速使用
<div id="demoProgress1"></div><script>
layui.use(['CircleProgress'], function () {var CircleProgress = layui.CircleProgress;// 快速使用new CircleProgress('#demoProgress1', {max: 100,value: 20});
});
</script>
6.6.2.全部参数
参数名称 | 说明 | 默认值 |
---|---|---|
max | 最大值 | |
value | 当前值 | |
clockwise | 是否顺时针方向 | true |
startAngle | 起始角度 | 0 |
textFormat | 文字样式 |
文字样式:
- vertical 垂直
- percent 百分比
- value 只显示值
- valueOnCircle 值显示在进度条上
- none 不显示文字
自定义文字样式:
new CircleProgress('#demoProgress9', {max: 12,value: 9,textFormat: function (value, max) {return value + ' dots';}
});
6.6.3.自定义样式
使用css自定义样式:
<div id="demoProgress1"></div><script>
layui.use(['CircleProgress'], function () {var CircleProgress = layui.CircleProgress;// 快速使用new CircleProgress('#demoProgress1', {max: 100,value: 20,textFormat: 'percent'});
});
</script><style>
/* 进度条选中的样式 */
#demoProgress1 .circle-progress-value {stroke-width: 8px; /* 粗度 */stroke: #3FDABA; /* 颜色 */
}/* 进度条未选中的样式 */
#demoProgress1 .circle-progress-circle {stroke-width: 6px;stroke: #E0FAF1;
}
</style>
此插件是使用svg实现的,想要实现更丰富的样式,可先了解下svg
6.7.1.快速使用
默认样式:
<div class="layui-tab layui-steps"><ul class="layui-tab-title"><li><i class="layui-icon layui-icon-ok">1</i><span class="layui-steps-title">已完成</span><span class="layui-steps-content">这里是该步骤的描述信息</span></li><li class="layui-this"><i class="layui-icon layui-icon-ok">2</i><span class="layui-steps-title">进行中</span><span class="layui-steps-content">这里是该步骤的描述信息</span></li><li><i class="layui-icon layui-icon-ok">3</i><span class="layui-steps-title">待进行</span><span class="layui-steps-content">这里是该步骤的描述信息</span></li></ul><div class="layui-tab-content"><div class="layui-tab-item">内容1</div><div class="layui-tab-item layui-show">内容2</div><div class="layui-tab-item">内容3</div></div>
</div>
<script>
layui.use(['steps'], function () {var steps = layui.steps;});
</script>
它的结构与layui的选项卡Tab一致,因为它就是在Tab的基础上增加的样式。
6.7.2.风格选择
迷你样式:
<!-- 多加一个layui-steps-small即可 -->
<div class="layui-tab layui-steps layui-steps-small"><!-- 省略...... -->
</div>
自定义图标:
<div class="layui-tab layui-steps layui-steps-small"><ul class="layui-tab-title"><li class="layui-this"><!-- 这里的图标可以任意修改 --><i class="layui-icon layui-icon-username"></i><span class="layui-steps-title">账号注册</span></li><li><i class="layui-icon layui-icon-camera"></i><span class="layui-steps-title">上传头像</span></li></ul><div class="layui-tab-content"><div class="layui-tab-item layui-show">内容1</div><div class="layui-tab-item">内容2</div></div>
</div>
垂直风格:
<!-- 多加一个layui-steps-vertical即可 -->
<div class="layui-tab layui-steps layui-steps-vertical"><!-- 省略...... -->
</div>
简洁风格:
<!-- 多加一个layui-steps-simple -->
<div class="layui-tab layui-steps layui-steps-simple"><ul class="layui-tab-title"><li>1.填写注册手机号</li><li class="layui-this">2.获取短信验证码</li><li>3.修改登录密码</li></ul><div class="layui-tab-content"><div class="layui-tab-item">内容1</div><div class="layui-tab-item layui-show">内容2</div><div class="layui-tab-item">内容3</div></div>
</div>
注意 简洁风格只有标题,没有图标、描述等
6.7.3.上一步下一步
<div class="layui-tab layui-steps" lay-filter="demoSteps"><!-- 省略...... -->
</div>
<script>
layui.use(['steps'], function () {var steps = layui.steps;steps.next('demoSteps'); // 下一步steps.prev('demoSteps'); // 上一步steps.go('demoSteps', 2); // 指定跳转,索引从0开始
});
</script>
也可以使用属性绑定:
<div class="layui-tab layui-steps"><!-- 省略...... --><a class="layui-btn" data-steps="prev">上一步</a><a class="layui-btn" data-steps="next">下一步</a><a class="layui-btn" data-steps="go" data-go="1">跳转第2步</a>
</div>
7.1.1.全部方法
方法 | 参数 | 描述 |
---|---|---|
merges(tableId, indexs, fields) | 见单独说明 | 合并单元格 |
bindCtxMenu(tableId, items) | 见单独说明 | 给表格行绑定鼠标右键 |
exportData(object) | 见单独说明 | 导出任意数据 |
exportDataX(object) | 见单独说明 | 导出任意数据(依赖社区excel模块) |
exportDataBack(object) | 见单独说明 | 后端导出任意数据(支持post提交参数) |
render(object) | 同layui表格 | 渲染表格,带后端排序功能 |
renderFront(object) | 同layui表格 | 渲染表格,前端分页、排序、搜索 |
layui.use(['tableX'], function () {var tableX = layui.tableX;
});
7.1.2.合并单元格
在table.render的done回调里面使用tableX.merges
方法:
table.render({elem: '#xTable2',cols: [[{type: 'numbers'},{field: 'parentName', title: '模块名称', sort: true},{field: 'authorityName', title: '菜单名称', sort: true}]],done: function () {tableX.merges('xTable2', [1]); }
});
参数说明:
tableX.merges('xTable2', [1]); // 合并第2列相同的单元格
tableX.merges('xTable2', [1], ['parentName']); // 合并第2列相同的单元格
tableX.merges('xTable2', [1, 2]); // 合并第2、3列相同的单元格
tableX.merges('xTable2', [1, 2], ['parentName', 'authorityName']); // 合并第2、3列相同的单元格tableX.merges('xTable2', [1, 2], false); // 在后面加一个false可解决排序冲突的问题
- 参数一 必填 表格的lay-filter
- 参数二 必填 要合并列的索引,数组类型
- 参数三 非必填 根据数据字段判断是否相同,为空时根据单元格的html内容判断
- 参数四 非必填 是否需要监听排序后重新合并,默认为true
7.1.3.行绑定鼠标右键
在table.render的done回调里面使用tableX.bindCtxMenu
方法:
table.render({elem: '#xTable3',cols: [[{field: 'nickName', title: '用户名'},{field: 'sex', title: '性别'}]],done: function () {tableX.bindCtxMenu('xTable3', [{icon: 'layui-icon layui-icon-edit',name: '修改此用户',click: function (d, tr) {layer.msg('点击了修改,userId:' + d.userId);}}, {icon: 'layui-icon layui-icon-close text-danger',name: '<span class="text-danger">删除此用户</span>',subs: [{icon: 'layui-icon layui-icon-camera',name: '逻辑删除',click: function (d) {layer.msg('点击了逻辑删除,userId:' + d.userId);}}, {icon: 'layui-icon layui-icon-picture-fine',name: '物理删除',click: function (d) {layer.msg('点击了物理删除,userId:' + d.userId);}}]}]);}
});
- 参数一 表格的id
- 参数二 右键菜单
- icon 图标
- name 标题
- click 点击事件,d是当前行的数据
根据不同行动态显示不同菜单,只需要把参数二换成function并return菜单数组即可:
tableX.bindCtxMenu('xTable3', function(d, tr) {if(d.userId === 1) {return [{icon: 'layui-icon layui-icon-close text-danger',name: '<span class="text-danger">删除此用户</span>',click: function (d, tr) {layer.msg('点击了删除,userId:' + d.userId);}}];} else {return [{icon: 'layui-icon layui-icon-edit',name: '修改此用户',click: function (d, tr) {layer.msg('点击了修改,userId:' + d.userId);}}];}
});
7.1.4.后端排序
tableX.render({elem: '#xTable3',url: '../../json/user.json',cols: [[{type: 'numbers'},{field: 'nickName', title: '用户名', sort: true},{field: 'sex', title: '性别', sort: true}]]
});
仅仅是把table.render换成tableX.render
就会在点击排序时自动传递sort
和order
参数,例如:user?page=1&limit=10&sort=sex&order=asc。
- sort 排序字段,值是点击排序列的field
- order 排序方式,升序是asc,降序是desc
注意:如果写了sort: true开启排序,一定要写field: 'xxx'
7.1.5.前端分页排序
tableX.renderFront({elem: '#xTable1',url: '../../json/userAll.json',page: true,cols: [[{field: 'nickName', title: '用户名', sort: true},{field: 'sex', title: '性别', sort: true}]]
});
仅仅是把table.render换成tableX.renderFront
就可以有前端分页和排序功能了,参数跟layui表格的参数一样,url方式你的接口可以返回全部数据,前端来分页,也支持data方式。
前端模糊搜索:
<input tb-search="xTable1" class="layui-input icon-search"/>
在页面任意位置加入上面输入框,通过tb-search
关联表格,就实现了对表格的模糊搜索功能。 还可以增加name属性来设置搜索时只搜索某些字段,多个字段通过逗号分隔:
<input tb-search="xTable1" name="sex,phone" class="layui-input icon-search"/>
刷新功能:
<button tb-refresh="xTable1" class="layui-btn">刷新</button>
在页面任意位置加入上面按钮,通过tb-refresh
关联表格。 也可以通过js刷新:
// url方式渲染的只能用此方法刷新
var insTb = tableX.renderFront({url: 'xxx'});
insTb.reloadUrl();// data方式渲染的只能用此方法刷新
var insTb = tableX.renderFront({data: []});
insTb.reloadData({data: dataList, page: {curr: 1}});
前端排序:
前端排序如果有field字段,会根据field字段的值来排序,如果有templet会根据templet转换后的值排序, templet可能会返回表单元素,比如switch开关等,这些元素无法用来排序,可以通过export-show
和export-hide
来控制。
<!-- switch开关列 -->
<script type="text/html" id="tableState"><input type="checkbox" lay-skin="switch" lay-text="正常|锁定" lay-filter="ckState" value="{{d.userId}}" {{d.state==0?'checked':''}}/><div class="export-show">{{d.state==0?'正常':'锁定'}}</div>
</script><!-- icon图标列 -->
<script type="text/html" id="tableState"><div class="export-hide">{{d.state==0?'<i class="layui-icon layui-icon-ok"></i>':'<i class="layui-icon layui-icon-close"></i>'}}</div><div class="export-show">{{d.state==0?'正常':'锁定'}}</div>
</script>
export-show
排序和导出时有效,表格展示时屏蔽export-hide
表格展示时有效,排序和导出时屏蔽
7.1.6.导出数据
tableX.exportData({cols: insTb.config.cols, // 表头配置data: table.cache.xTable3, // 数据,支持url方式fileName: '用户表' // 文件名称
});// exportDataX是新增的方法,参数与上面一摸一样
tableX.exportDataX({});
参数 | 必填 | 说明 | 默认 |
---|---|---|---|
cols | 是 | 表头配置 | |
data | 是 | 导出的数据,支持数组和string的url | |
fileName | 否 | 导出的文件名称 | table |
expType | 否 | 导出的文件类型 | xls(默认)、csv、xlsx |
option | 否 | url方式的配置 |
如果data是string类型会把data当url请求数据,option是请求的配置,跟表格的配置一样,配置method、where、headers等, 接口返回的格式也要跟表格一样包含code、count、data等信息。
cols的配置也跟表格一样,是一个多维数组,可以通过insTb3.config.cols
来获取表格的cols,也可以重写。
导出的数据会包含templet转换,如果templet返回的是switch开关、icon图标等,可以通过export-show
和export-hide
写两份, 一份用于表格的展示,一份用于表格的导出显示,具体用法参考前面前端排序章节的介绍。
cols也可以重写:
tableX.exportData({cols: [[{field: 'username', title: '账号'},{field: 'nickName', title: '用户名'}]],data: table.cache.xTable3,fileName: '用户表'
});
exportDataX方法使用的是社区excel模块导出的,是真正的xls格式,exportData以及layui自带的导出都是假的xls格式,如果数字前面有0会自动去掉0,exportDataX可解决此问题。
7.1.7.导出全部、搜索
后端分页时如何导出全部数据:
tableX.exportDataX({cols: insTb.config.cols,data: 'listAll.json',fileName: '用户表'
});
// 后端再写一个查询全部的接口,data写接口地址
导出搜索后的全部数据:
var lastWhere; // 记录搜索的条件
// 表格搜索
form.on('submit(formSubSearchUser)', function (data) {lastWhere = data.field;insTb.reload({where: data.field}, 'data');
});tableX.exportDataX({cols: insTb.config.cols,data: 'listAll.json',option: {where: lastWhere},fileName: '用户表'
});
在options里面加一个where把搜索条件传给后端。
7.1.8.后端导出
后端导出本质就是下载文件,一般用window.open(url)即可,如果要传递参数、post提交,那就麻烦了,tableX进行了完美的封装:
tableX.exportDataBack('user/export', {sex: '男'});tableX.exportDataBack('user/export', {sex: '男'}, 'post');
- 参数一 后端的url
- 参数二 传递的参数
- 参数三 请求方式
如果是get方式,会使用?和&拼接参数,如果是post方式,会创建一个隐藏的表单来提交, 如果你的参数有复杂的类型,比如json格式,建议用post的形式,此方法也可以用来做post方式下载文件的操作。
7.2.1.验证规则
规则 | 描述 | 提示信息 |
---|---|---|
phoneX | 手机号 | 请输入正确的手机号 |
emailX | 邮箱 | 邮箱格式不正确 |
urlX | 网址 | 链接格式不正确 |
numberX | 数字 | 只能填写数字 |
dateX | 日期 | 日期格式不正确 |
identityX | 身份证 | 请输入正确的身份证号 |
psw | 密码 | 密码必须5到12位,且不能出现空格 |
equalTo | 重复 | 两次输入不一致 |
digits | 整数 | 只能输入整数 |
digitsP | 正整数 | 只能输入正整数 |
digitsN | 负整数 | 只能输入负整数 |
digitsPZ | 非负整数 | 只能输入正整数和0 |
digitsNZ | 非正整数 | 只能输入负整数和0 |
h5 | 兼容h5的规则 |
使用示例:
<form class="layui-form"><input class="layui-input" placeholder="请输入手机号" lay-verType="tips" lay-verify="phoneX"/><input class="layui-input" placeholder="请输入手机号" lay-verType="tips" lay-verify="required|phoneX"/><input class="layui-input" placeholder="请输入整数" lay-verType="tips" lay-verify="digits"/><input class="layui-input" placeholder="请输入正整数" lay-verType="tips" lay-verify="digitsP"/>
</form>
<script>
layui.use(['formX'],function(){var formX = layui.formX; // 要引入formX模块才会生效
});
</script>
equalTo用法,可以用来验证两次输入是否一致:
<form class="layui-form"><input id="demoPsw" class="layui-input" placeholder="请输入密码" lay-verType="tips" lay-verify="required|psw"/><input class="layui-input" placeholder="请再次输入密码" lay-verType="tips" lay-verify="equalTo" lay-equalTo="#demoPsw" lay-equalToText="两次输入密码不一致"/>
</form>
属性 | 描述 |
---|---|
lay-equalTo | 关联输入框的dom选择器 |
lay-equalToText | 自定义提示文本 |
h5用法:
属性 | 描述 |
---|---|
minlength | 最少输入字符长度 |
maxlength | 最多输入字符长度 |
min | 最小输入数值 |
max | 最大输入数值 |
<form class="layui-form"><input class="layui-input" placeholder="最少输入5个字符" minlength="5"lay-verType="tips" lay-verify="required|h5"/><input class="layui-input" placeholder="最多输入10个字符" maxlength="10"lay-verType="tips" lay-verify="h5"/><input class="layui-input" type="number" placeholder="值只能在-9到9之间" min="-9" max="9"lay-verType="tips" lay-verify="required|numberX|h5"/>
</form>
phoneX、emailX等与layui自带phone、email等的区别是如果没有输入不会验证,输入了才验证格式。
7.2.2.扩展方法
方法 | 描述 |
---|---|
val(filter, object) | 赋值表单,解决top.layui.form.val()无效bug |
renderSelect(option) | 渲染select封装 |
startTimer(elem, time, format) | 按钮验证码倒计时封装 |
formUpdatedField(field, oldField) | 获取表单修改过的数据 |
使用方法:
layui.use(['formX'],function(){var formX = layui.formX;// 赋值表单,支持top.formX.val()用法formX.val('userForm', {name: 'user01'});
});
7.2.3.渲染select封装
<select id="sel"></select>
<script>
layui.use(['formX'],function(){var formX = layui.formX;// 数据方式formX.renderSelect({elem: '#sel',data: [{id: 1, name: '张三'},{id: 2, name: '李四'}],name: 'name',value: 'id',hint: '请选择用户',initValue: 1,done: function() {}});// 异步方式formX.renderSelect({elem: '#sel',data: 'user.json',name: 'name',value: 'id',hint: '请选择用户',done: function(data) {},method: 'get',where: {page: 20},header: {token: 'xxx'},async: true,error: function(xhr, res){}});
});
</script>
基础参数:
- elem 要渲染的select
- data 数据源,可以是数组,也可以是url
- name 显示的字段名称
- value 值的字段名称
- hint 未选择提示文字
- initValue 默认回显的数据
- done 渲染完成后的回调
- error data为url时请求失败的回调
- method data为url时请求方式
- where data为url时请求参数
- header data为url时请求header
- async data为url时请求时否是异步
后端返回数据格式为{"data": [], "code": 0}
,data有数据就是请求成功,没有数据就进入error,code等于多少都可以, 如果数据不是对象的形式,name和value可不填:
formX.renderSelect({elem: '#sel',data: ['张三','李四']
});
7.2.4.验证码倒计时
<button id="btnSend" class="layui-btn">发送验证码</button><script>layui.use(['formX'],function(){var formX = layui.formX;// 按钮倒计时30sformX.startTimer('#btnSend', 30);// 自定义倒计时文字,默认是30s,29s,28s...formX.startTimer('#btnSend', 30, function(time){return time + 's 后可继续发送';});
});
</script>
7.2.5.获取修改字段
var user = {sex: 'male', age: 18};
form.val('userForm', user); // 表单回显数据
// 获取表单修改后的字段
var field = formX.formUpdatedField(form.val('userForm'), user);
console.log(field);
利用这个方法可以做判断用户是否修改了表单:
var user = {sex: 'male', age: 18};
form.val('userForm', user); // 表单回显数据
// 监听表单提交
form.on('submit(submit-user)', function (data) {var u = formX.formUpdatedField(data.field, user);if(!u) { alert('你没有做任何修改'); }return false;
});
7.3.1.打印当前页面
printer.print();printer.print({hide: ['.layui-btn', '#btn01'], // 打印时隐藏的元素horizontal: true, // 是否横向打印blank: true, // 是否打开新页面打印close: true, // 如果是打开新页面,打印完是否关闭iePreview: true // 是否兼容ie打印预览
});
参数都是可以选参数,默认值已经符合大多数需求。
7.3.2.设置不打印元素
<div class="hide-print">非打印内容</div>
加hide-print
这个class即可,可以跟hide
参数叠加使用。
7.3.3.打印自定义内容
var pWindow = printer.printHtml({html: '<span>xxxx</span>', // 要打印的内容horizontal: true, // 是否横向打印blank: true, // 是否打开新页面打印close: true, // 如果是打开新页面,打印完是否关闭iePreview: true, // 是否兼容ie打印预览print: true // 如果是打开新窗口是否自动打印
});
打印表格时可以给table加print-table
这个class来设置表格的边框样式:<table class="print-table">
。
如果print为false关闭自动打印,可以使用
pWindow.print()
触发打印。
7.3.4.分页打印
printer.printPage({htmls: ['<span>xxxx</span>', // 要打印的内容'<span>xxxx</span>'],style: '<style>span{color:red;}</style>',// 页面样式horizontal: true, // 是否横向打印blank: true, // 是否打开新页面打印close: true, // 如果是打开新页面,打印完是否关闭iePreview: true, // 是否兼容ie打印预览print: true, // 如果是打开新窗口是否自动打印padding: undefined, // 页面间距debug: false, // 调试模式height: undefined, // 页面高度width: undefined // 页面宽度
});
参数都是可选参数:
- htmls 数组,代表每一页;
- style 样式,也可以写
<link rel="stylesheet">
的形式; - padding 页面间距,例如写'10px';
- debug 调试模式,每一页会加红色边框,便于调试大小;
7.3.5.拼接html
var htmlStr = printer.makeHtml({title: '网页标题',style: '<link rel="stylesheet" href="layui.css"><script type="text/javascript" src="layui.js"><\/script>',body: $('#xxx').html()
});
7.4.1.快速使用
layui.use(['contextMenu'], function () {var contextMenu = layui.contextMenu;// 重写整个页面右键菜单contextMenu.bind('html', [{icon: 'layui-icon layui-icon-snowflake',name: '菜单一',click: function (e, event) {// 通过$(event.currentTarget)可获取事件触发的元素alert('点击了菜单一');}}, {name: '菜单二',click: function (e) {alert('点击了菜单二');}}]);
});
- 参数一 绑定元素
- 参数二 菜单数组
菜单数组可支持无限极:
[{icon: 'xxxxx',name: '菜单三',subs: [{icon: 'xxxxx',name: '子菜单一',click: function (e, event) {alert('点击了子菜单一');}}]
}]
- icon 图标
- name 菜单名
- click 点击事件
- subs 子菜单(支持无限极)
click事件里面的e是右键菜单的事件对象,event才是绑定的目标元素的事件对象
7.4.2.自定义使用
例如用于点击事件:
$('#btn').click(function (e) {var x = $(this).offset().left;var y = $(this).offset().top + $(this).outerHeight() - $('html,body').scrollTop();contextMenu.show([{name: '按钮菜单一',click: function () {}}], x, y, e);e.preventDefault();e.stopPropagation();
});
你可以自己绑定事件,通过show方法显示出来,参数说明:
- 参数一 菜单数组
- 参数二 x坐标
- 参数三 y坐标
- 参数四 e 原始事件对象
7.4.3.动态元素绑定
对于动态生成的元素可以使用事件委托的方式来绑定:
// 对.btn元素绑定鼠标右键
$ (document). bind('contextmenu', '.btn', function (e) {contextMenu.show([{icon: 'layui-icon layui-icon-set',name: '删除',click: function (e, event) {layer.msg('点击了刪除');}}],e. clientX, e. clientY, e);return false;
});
7.5.1.快速使用
后台管理页面大多用数据表格展示,如果要使用网格、瀑布流、卡片列表等形式,分页、自动渲染、搜索、排序等功能都需要自己实现, 极其麻烦,dataGrid模块就是对非表格形式的列表页面实现类似数据表格的功能,也在使用方法上与数据表格大致相同。
<div id="demoGrid"></div><!-- 容器 --><!-- 模板 -->
<script type="text/html" id="demoGridItem"><div><h2>{{d.title}}</h2><p>{{d.content}}</p><a lay-event="add">添加</a><a lay-event="edit">修改</a></div>
</script><script>
layui.use(['dataGrid'], function () {var dataGrid = layui.dataGrid;/* 渲染 */var ins = dataGrid.render({elem: '#demoGrid', // 容器templet: '#demoGridItem', // 模板url: 'json/list.json', // 数据接口page: {limit: 5} // 开启分页});/* item点击事件 */dataGrid.on('item(demoGrid)', function (obj) {obj.data; // 当前操作的数据对象obj.elem; // 当前操作的dom元素obj.del(); // 删除当前itemobj.update({title: 'new title'}); // 修改当前itemlayer.msg('点击了第' + (obj.index + 1) + '个');});/* item里面的lay-event的点击事件 */dataGrid.on('tool(demoGrid)', function (obj) {var data = obj.data;if (obj.event === 'add') {layer.msg('点击了添加');} else if (obj.event === 'edit') {layer.msg('点击了编辑');} });/* item双击事件 */dataGrid.on('itemDouble(demoGrid)', function (obj) {});/* 监听复选框选择 */dataGrid.on('checkbox(demoGrid)', function (obj) {console.log(obj.checked); // 当前是否选中状态console.log(obj.data); // 选中行的相关数据console.log(obj.type); // 如果触发的是全选,则为all});});
</script>
7.5.2.全部参数
参数 | 类型 | 说明 | 示例 |
---|---|---|---|
elem | String/DOM | 指定容器的选择器或DOM | "#demo" |
templet | String | item模板,模板遵循 laytpl 语法 | |
data | Array | 直接赋值数据,也可前端分页 | [{},{},{}] |
url | String | 接口地址 | |
method | String | 接口http请求类型,默认:get | |
where | Object | 接口的请求参数 | where: {id: 123} |
headers | Object | 接口的请求头 | headers: {token: 'sasasas'} |
contentType | String | 发送到服务端的内容编码类型 | contentType: 'application/json' |
parseData | Function | 数据格式解析的回调函数 | |
request | Function | 用于对分页请求的参数重新设定名称 | 默认是page、limit |
useAdmin | Boolean | 是否使用admin.ajax | 默认false |
done | Function | 数据渲染完的回调 | |
page | Object | 开启分页,配置分页参数 | |
loadMore | Object | 开启加载更多,配置加载更多参数 |
parseData和request参数说明:
var ins = dataGrid.render({elem: '#demoGrid',templet: '#demoGridItem',url: 'json/list.json',parseData: function(res) {return {code: res.status,msg: res.message,count: res.total,data: res.list}},request: {pageName: 'page', limitName: 'limit'}
});
渲染完成的回调done说明:
dataGrid.render({done: function(dataList, curr, count) {dataList; // 当前页数据curr; // 当前第几页count; // 总数量}
});
7.5.3.分页功能
使用page参数开启分页,page参数同layui分页组件的参数一致前往查看。
dataGrid.render({elem: '#demoGrid', // 容器templet: '#demoGridItem', // 模板url: 'json/list.json', // 数据接口page: {limit: 5} // 开启分页
});
7.5.4.加载更多功能
dataGrid.render({elem: '#demoGrid', // 容器templet: '#demoGridItem', // 模板url: 'json/list.json', // 数据接口loadMore: {limit: 5} // 开启加载更多
});
loadMore和page只能二选一,loadMore的可选参数:
参数 | 说明 | 默认值 |
---|---|---|
class | 自定义class | '' |
limit | 每页多少条 | 10 |
text | 显示文字 | '加载更多' |
loadingText | 加载中文字 | '加载中...' |
noMoreText | 无数据文字 | '没有更多数据了~' |
errorText | 加载失败文字 | '加载失败,请重试' |
7.5.5.实例方法
var ins = dataGrid.render({});ins.reload(); // 重载
ins.reload({page: {curr: 2} }); // 跳到第二页ins.update(index, fields, type); // 修改数据
// index是索引,fields是要修改的字段
// type 0整个item更新, 1只更新item子元素, 2只更新数据不更新itemins.del(index); // 删除itemins.getData(); // 获取当前数据ins.checkStatus(); // 获取选中行数据
7.5.6.自动渲染
<div id="demoGrid" lay-data="{url: 'json/list.json', page: {limit: 5} }" data-grid><script type="text/html" data-grid-tpl><div><h2>{{d.title}}</h2><p>{{d.content}}</p><a lay-event="edit">修改</a></div></script>
</div>
通过添加data-grid和data-grid-tpl属性,dataGrid组件便会自动渲染,通过lay-data属性进行参数配置。
7.6.1.快速使用
layui.use(['fileChoose'], function () {var fileChoose = layui.fileChoose;fileChoose.open({fileUrl: '', // 文件查看的urllistUrl: '../template/file/files.json', // 文件列表的urlwhere: {access_token: 'xxxxxx' },num: 3, // 最多选择数量dialog: {offset: '60px'},onChoose: function (urls) {layer.msg('你选择了:' + JSON.stringify(urls), {icon: 1});}});
});
7.6.2.全部参数
参数 | 描述 | 默认值 |
---|---|---|
fileUrl | 文件查看的url | |
listUrl | 文件列表的url | |
where | 文件列表请求参数 | {} |
num | 文件选择的数量 | 1 |
onChoose | 选择后回调 | |
upload | 文件上传配置(同layui配置) | {} |
dialog | 弹窗配置(同layui配置) | {} |
menu | 点击弹出的菜单 | 数组类型 |
menuClick | 菜单点击事件处理 | |
response | 接口数据格式化 |
菜单配置及点击事件:
fileChoose.open({menu: [{name: '预览',event: 'preview'}, {name: '复制',event: 'copy'}, {name: '<span style="color: red;">删除</span>',event: 'del'}],menuClick: function(event, item) {// event 事件名称// item 当前数据}
});
name菜单项名称,event点击事件名称
接口数据格式化:
fileChoose.open({response: {method: 'get', // 请求方式code: 0, // 成功码,默认200name: 'name', // 文件名称字段名称url: 'url', // 文件url字段名称smUrl: 'smUrl', // 文件缩略图字段名称isDir: 'isDir', // 是否是文件夹字段名称,boolean类型dir: 'dir' // 当前文件夹参数名称}
});
接口数据返回的格式需要为:
{"code": 200,"msg": "请求成功","data": [{"name": "图片一","url": "2019/07/11/001.png","smUrl": "sm/2019/07/11/001.png","isDir": false}]
}
code、msg、data是必须按这个名字的,name、url、smUrl、isDir这几个字段的名称可以通过response参数配置,也可以加其他字段, 比如id、create_time等,这些字段会在菜单点击事件和选择回调事件中返回。
如果你的接口返回的数据不是code、msg,是其他的,比如status、message,可以使用parseData参数格式化:
fileChoose.open({response: {parseData: function(res){return {code: res.status,msg: res.message,data: res.list}}}
});
如果是文件夹,点击文件夹会重新请求接口,并且传递文件夹的名称,传递的字段名称可以通过response.dir修改。
上传文件上传成功后默认会进入到当前日期生成的dir下面,你可以后端上传成功的接口返回dir指定上传成功后要进入的dir, 也可以把上传前端传递的dir原封不动的返回:
{"code": 200,"msg": "上传成功", "dir": "/2020/0516"}
不同文件显示不同的图标是前端根据文件url的后缀名称来判断的,在之前版本是服务器根据文件的content-type判断的。
8.1.鼠标滚轮监听
此插件来源于 jquery-mousewheel,使用方式:
layui.use(['mousewheel'], function () {var $ = layui.jquery;// 滚动监听$('#xxx').on('mousewheel', function (event) {console.log(event.deltaX, event.deltaY, event.deltaFactor);event.stopPropagation(); // 阻止事件冒泡event.preventDefault(); // 阻止默认事件});});
event对象中可以获取如下三个属性值:
- deltaX:值为负的(-1)表示滚轮向左滚动,值为正的(1)表示滚轮向右滚动。
- deltaY:值为负的(-1)表示滚轮向下滚动。值为正的(1)表示滚轮向上滚动。
- deltaFactor:增量因子,通过
deltaFactor*deltaX
或者deltaFactor*deltaY
可以得到浏览器实际的滚动距离。
8.2.二维码模块
此插件来源于 qrcodejs,使用方式:
<div id="xxx"></div>
<script>layui.use(['QRCode'], function () {var $ = layui.jquery;var QRCode = layui.QRCode;// 二维码var demoQrCode = new QRCode(document.getElementById("xxx"), {text: "Hello Word!",width: 101, // 宽度height: 101, // 高度colorDark: "#000000", // 颜色colorLight: "#ffffff", // 背景颜色correctLevel: QRCode.CorrectLevel.H});// 更换内容demoQrCode.makeCode("Easyweb");});
</script>
8.3.引导插件
此插件来源于 intro.js,并对样式进行了微调,使用方式:
<div data-step="1" data-intro="这是步骤一">步骤一</div>
<div data-step="2" data-intro="这是步骤二">步骤二</div>
<script>layui.use(['introJs'], function () {var introJs = layui.introJs;// 初始化introJs().start();});
</script>
8.4.剪贴板
此插件来源于 clipboard.js,使用方式:
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git">
<button id="btnCopy" data-clipboard-target="#foo">复制</button>
<script>layui.use(['ClipboardJS'], function () {var ClipboardJS = layui.ClipboardJS;var clipboard = new ClipboardJS('#btnCopy');clipboard.on('success', function(e) {e.clearSelection();});clipboard.on('error', function(e) {console.error('Action:', e.action);});});
</script>
按钮通过data-clipboard-target
绑定的不一定是input,div也可以,也不一定用id,jquery选择器都可以。
8.5.视频播放器
视频播放器使用的是西瓜视频开源的xgplayer,使用方式:
<div id="demoVideo"></div><script>layui.use(['Player'], function () {var Player = layui.Player;// 视频播放器var player = new Player({id: "demoVideo",url: "//s1.pstatp.com/cdn/expire-1-M/byted-player-videos/1.0.0/xgplayer-demo.mp4", // 视频地址poster: "https://imgcache.qq.com/open_proj/proj_qcloud_v2/gateway/solution/general-video/css/img/scene/1.png", // 封面fluid: true, // 宽度100%playbackRate: [0.5, 1, 1.5, 2], // 开启倍速播放pip: true, // 开启画中画lang: 'zh-cn'});// 开启弹幕var dmStyle = {color: '#ffcd08', fontSize: '20px'};var player = new Player({id: "demoVideo2",url: "http://demo.htmleaf.com/1704/201704071459/video/2.mp4", // 视频地址autoplay: false,fluid: true, // 宽度100%lang: 'zh-cn',danmu: {comments: [{id: '1', start: 0, txt: '空降', color: true, style: dmStyle, duration: 15000},{id: '2', start: 1500, txt: '前方高能', color: true, style: dmStyle, duration: 15000},{id: '3', start: 3500, txt: '弹幕护体', color: true, style: dmStyle, duration: 15000},]}});});
</script>
8.6.富文本编辑器
富文本编辑器使用的是TinyMCE,查看中文文档。
<textarea id="demoEditor"></textarea><script type="text/javascript" src="assets/libs/tinymce/tinymce.min.js"></script>
<script>
layui.use(['layer'], function () {var $ = layui.jquery;var layer = layui.layer;// 渲染富文本编辑器tinymce.init({selector: '#demoEditor',height: 525,branding: false,language: 'zh_CN',plugins: 'code print preview fullscreen paste searchreplace save autosave link autolink image imagetools media table codesample lists advlist hr charmap emoticons anchor directionality pagebreak quickbars nonbreaking visualblocks visualchars wordcount',toolbar: 'fullscreen preview code | undo redo | forecolor backcolor | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | formatselect fontselect fontsizeselect | link image media emoticons charmap anchor pagebreak codesample | ltr rtl',toolbar_drawer: 'sliding',images_upload_url: '../../../json/tinymce-upload-ok.json',file_picker_types: 'media',file_picker_callback: function (callback, value, meta) {layer.msg('演示环境不允许上传', {anim: 6});},init_instance_callback: function (editor) {console.log(editor);// 编辑器渲染完成回调,回显值应该在这里回显// tinymce.get('demoEditor').setContent('<span>Hello</span>');}});// 获取内容var content = tinymce.get('demoEditor').getContent();// 获取纯文本var content = tinymce.get('demoEditor').getContent({format: 'text'});// 设置内容tinymce.get('demoEditor').setContent('<span>Hello</span>');// 插入内容tinymce.get('demoEditor').insertContent('
EASY spa单页面版文档相关推荐
- layui登录页面写入数据_layuiAdmin单页版文档
该文档适用于 layuiAdmin 专业版(单页面),阅读之前请务必确认是否与你使用的版本对应. 熟练掌握 layuiAdmin 的前提是熟练掌握 layui,因此除了本篇文档, layui 的文档 ...
- SPA单页应用的优缺点
SPA单页应用的优缺点 Single Page Web Application是一种特殊的Web应用,其所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML.JavaScrip ...
- java 单页面spa_Javascript 与 SPA单页Web富应用
书单推荐 # <单页Web应用:JavaScript从前端到后端>http://download.csdn.net/detail/epubitbook/8720475 # <MVC的 ...
- bash: 无法为立即文档创建临时文件: 权限不够_世界顶级Linux大牛耗时三年总结出3000页Linux文档...
众所皆知的,Linux的核心原型是1991年由托瓦兹(Linus Torvalds)写出来的,但是托瓦兹为何可以写出Linux这个操作系统?为什么它要选择386的计算机来开发?为什么Linux的发展可 ...
- word取消下一页_word文档页码设置及文中小箭头清除办法
在很长一段时间里,朋友圈流传的这样一段话:世人慌慌张张,不过图碎银几两:可偏偏就是这几两碎银,能免饥荒,能定安康 ,能解世人惆怅... 问:word怎么从第二页开始加页码 答:施工方案可以先删除自动生 ...
- 阿里Java面试答案【283页PDF文档免费领】
怎样才能拿到大厂的offer,没有掌握绝对的技术,那么就要不断的学习 如何拿下阿里等大厂的offer的呢,今天分享一个秘密武器,资深架构师整理的Java核心知识点,面试时面试官必问的知识点,篇章包括了 ...
- SPA 单页Web应用
定义 单页 Web 应用 (single-page application 简称为 SPA) 是一种特殊的 Web 应用.它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTM ...
- 万彩办公大师多页PDF文档去掉空白部分合并到同一页
前置条件:下载万彩办公大师. 方法如下: 1.先使用"PDF页面分割"工具将PDF的每一个页面的空白部分通过分割线选中分割出来,保存为"文档1".(分割之后空白 ...
- wps打印缩放到一页_WPS文档过长时,如何在A4纸上完美打印
本教程适用版本:WPS Office 2019 PC版点此使用 现在WPS已经是不可或缺的办公软件了,大家在办公时肯定会遇到Excel表格打印的问题,小编就会时常遇到一个头疼的问题,就是在表格过长的时 ...
最新文章
- php设计模式的六大原则(二):开闭原则
- ssm使用全注解实现增删改查案例——applicationContext-servlet.xml
- IntelliJ IDEA 如何设置编辑窗口的背景图片
- python3.5兼容2.7吗_Python版本2.7切3.5和3.5切2.7
- HTML day02
- 计算机部门 消防安全隐患,市计算机:消防隐患勿轻视,安全意识常在心
- 学习笔记01:《开放平台产品成长之路-POP》
- scala 协变和逆变_Scala方差:协变,不变和逆变
- LayaAir UI 组件 # Button 按钮
- 淘宝API接口 item_search - 按关键字搜索淘宝商品
- 木本坚果的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- tpc ds mysql_TPC-DS 生成数据
- OAuth2第三方登录快速接入
- 两种方法简单实现网站随机语录的显示
- Doxygen使用教程
- excel不显示0_Excel中把0显示为空白的三种解决方法
- 【NOIP2014模拟11.2A组】福慧双修
- java创建byte数组_java.创建一个byte数组,long length = file.length(); byte[] bytes =
- VoLTE典型拆线原因代码及原因
- JDK7安装和配置 JAVA JDK7安装配置教程
热门文章