专栏首页小尘哥的专栏thymeleaf中使用layui

thymeleaf中使用layui

layui已经提供了一整套的UI布局及相关组件,并且有相当完善的api文档,本文重点在于thymeleaf中如何使用layui,包括公用部分的提取,而非简单的layui的用法。

先上两个效果图

列表.png

表单.png

一、思路

  1. 像传统的一样建文件头和尾(但是又和传统的写法不同,见下面代码)
  2. 定义公用js--common.js
  3. 定义公用css--用来重写一些样式或者自定义样式
  4. 编写列表页
  5. 编写表单页

二、文件头和尾

头部引入css,尾部引入js,定义两个模板(一个也可以,里面的碎片分开写,我喜欢写两个分别引入),注意th:fragment,fragment即碎片,可以在模板任何位置引入,此处为分别定义名为header和js_footer的碎片,以供后面引用

样式文件 link.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
<div th:fragment="header">
 <meta charset="utf-8"/>
 <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
 <!-- Tell the browser to be responsive to screen width -->
 <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
 <link rel="stylesheet" th:href="@{/js/layui/css/layui.css}"/>
 <link rel="stylesheet" th:href="@{/css/common.css}"/>
</div>
</html>
js文件 script.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
<div th:fragment="js_footer">
 <script th:src="@{/js/layui/layui.all.js}"></script>
 <script th:src="@{/js/common/common.js}"></script>
 <!-- 让IE8/9支持媒体查询,从而兼容栅格 -->
 <!--[if lt IE 9]>
 <script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
 <script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
 <![endif]-->
</div>
<script>
 var basePath='http://www.baidu.com';
</script>
</html>

三、公用js

该文件包含几个方法:

 1.initTable 初始化带分页的table,注意其中的request属性,可以配置和你后台Page对象对应的属性,具体可以参考layui官方文档 

2.searchTable table的搜索功能,调用layui table模块的的重载功能,参数组建思路:获取序列化的表单,组装成json对象 

3.upload 文件上传 

4.openFrame 打开弹出层,基于最顶层弹出

var Common = function () {
 var initTable = function (ele, url, cols, table, doneCallBack) {
 return table.render({
 elem: ele
 , url: url
 , method: 'POST'
 , cellMinWidth: 80 //全局定义常规单元格的最小宽度,layui 2.2.1 新增
 , cols: cols
 , page: {
 limits: [10, 20, 50, 100]
 },
 request: {
 pageName: 'current',
 limitName: 'size'
 },
 done: function (res, curr, count) {
 if (typeof(doneCallBack) === "function") {
 doneCallBack(res);
 }
 }
 });
 };

 var searchTable = function (formId, tableIns) {
 var queryParams = getParams(formId);
 tableIns.reload({
 where: {condition: queryParams},
 page: {
 curr: 1 //重新从第 1 页开始
 }
 });
 };

 var getParams = function (formId) {
 var $ = layui.jquery;
 var _params = {};
 $.each($('#' + formId).serializeArray(), function (i, field) {
 if (null != field.value && "" != field.value) {
 _params[field.name] = field.value;
 }
 });
 return _params;
 };

 var upload = function (eleId, layUpload, done, error, accept, exts) {
 layUpload.render({
 elem: eleId //绑定元素
 , url: '/upload/' //上传接口
 , accept: accept === undefined ? 'file' : accept
 , exts: exts === undefined ? 'jpg|png|gif|bmp|jpeg' : exts
 , done: function (res) {
 //上传完毕回调
 if (typeof (done) === 'function') {
 done(res)
 }
 }
 , error: function () {
 //请求异常回调
 if (typeof (error) === 'function') {
 error()
 }
 }
 });
 };

 var openFrame = function (url, title, width, height) {
 width = width === undefined ? '900px' : width;
 height = height === undefined ? '500px' : height;
 return top.layer.open({
 area: [width, height],
 type: 2,
 title: title,
 content: url //这里content是一个URL,如果你不想让iframe出现滚动条,你还可以content: ['http://sentsin.com', 'no']
 });
 };
 return {
 initTable: function (ele, url, cols, table, doneCallBack) {
 return initTable(ele, url, cols, table, doneCallBack);
 },
 searchTable: function (formId, table) {
 searchTable(formId, table);
 },
 uploadFile: function (eleId, layUpload, done, error, accept, exts) {
 upload(eleId, layUpload, done, error, accept, exts);
 },
 openFrame: function (url, title, width, height) {
 return openFrame(url, title, width, height);
 }
 }
}();

四、公用css

这个可以根据个人喜好或者项目实际情况自己定义

.form-body{
 margin-top: 4%
}
.layui-input-inline{
 width: 350px !important;
}

五、列表页

整个html除了头部的引入,整体分为三部分: 1.上面form为搜索内容部分 2.中间一个table为主窗口 3.注意一个id="toolBars"的js,为工具条,用于追加在每一列的后面 4.可以看到下面页面初始化等都调用了Common.js中的对应方法

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
<head>
 <title>Title</title>
 <div th:replace="common/links::header"></div>
 <div th:replace="common/script::js_footer"></div>
</head>
<body>
<fieldset class="layui-elem-field">
 <legend>条件搜索</legend>
<form class="layui-form" style="text-align: center" id="searchForm">
 <div class="layui-form-item">
 <div class="layui-inline">
 <label class="layui-form-label">手机号</label>
 <div class="layui-input-inline">
 <input type="tel" name="mobile" autocomplete="off" class="layui-input">
 </div>
 </div>
 <div class="layui-inline">
 <label class="layui-form-label">用户名</label>
 <div class="layui-input-inline">
 <input type="text" name="username" autocomplete="off" class="layui-input">
 </div>
 </div>
 </div>
 <div class="layui-form-item">
 <div class="layui-input-block">
 <button class="layui-btn" id="searchBtn" type="button">搜索</button>
 <button type="reset" class="layui-btn layui-btn-primary">重置</button>
 <button type="reset" class="layui-btn layui-btn-primary">新增</button>
 </div>
 </div>
</form>
</fieldset>
<hr class="layui-bg-green">
<table class="layui-hide" id="userTable" lay-filter="userFilter"></table>
<script type="text/html" id="toolBars">
 <a class="layui-btn layui-btn-xs" lay-event="detail">查看</a>
 <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
 <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>

 <!-- 这里同样支持 laytpl 语法,如: -->
 <a class="layui-btn layui-btn-xs" lay-event="check">审核</a>
</script>
<script>
 cols=[[
 {checkbox: true, fixed: true}
 ,{field:'username', title: '用户名'} //width 支持:数字、百分比和不填写。你还可以通过 minWidth 参数局部定义当前单元格的最小宽度,layui 2.2.1 新增
 ,{field:'mobile', title: '手机号', sort: true}
 ,{field:'nickname', title: '昵称'}
 ,{field:'lastLoginTime', title: '最后登录时间'}
 ,{field:'ip', title: '最后登录ip', align: 'center'} //单元格内容水平居中
 ,{field:'op',title: '操作', align:'center', toolbar: '#toolBars'} //这里的toolbar值是模板元素的选择器
 ]];

 layui.use('table', function(){
 var table = layui.table,$ = layui.jquery;
 table.on('tool(userFilter)', function(obj){
 var data = obj.data; //获得当前行数据
 var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
 if(layEvent === 'detail'){ //查看
 //TODO detail
 } else if(layEvent === 'del'){ //删除
 top.layer.confirm('真的删除行么', function(index){
 //TODO do delete
 });
 } else if(layEvent === 'edit'){ //编辑
 Common.openFrame('/sys/user/to-edit?id=' + data.id,'修改用户信息');
 }
 });
 var initTable = Common.initTable('#userTable','/sys/user/query-page',cols,table);
 $('#searchBtn').on('click',function () {
 Common.searchTable('searchForm',initTable);
 })
 });
</script>
</body>
</html>

六、表单页

列表出来之后表单就更简单了,只需要去layui官网找个表单,根据自己的实际情况布局即可,特别说明的是校验,即verify.js,用于自己对验证方法的扩展 form.html

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
<head>
 <title>Title</title>
 <div th:replace="common/links::header"></div>
 <div th:replace="common/script::js_footer"></div>
 <script th:src="@{/js/common/verify.js}"></script>
</head>
<body class="form-body">
<form class="layui-form " action="">
 <div class="layui-form-item layui-col-md6 layui-col-md-offset2">
 <label class="layui-form-label">用户名</label>
 <div class="layui-input-inline form-length350">
 <input type="text" name="username" th:value="${user.username}" lay-verify="required|username" placeholder="请输入用户名" autocomplete="off" class="layui-input">
 </div>
 <div class="layui-form-mid layui-word-aux">*6-12个字符</div>
 </div>
 <div class="layui-form-item layui-col-md4 layui-col-md-offset2">
 <label class="layui-form-label">密码框</label>
 <div class="layui-input-inline">
 <input type="password" name="password" lay-verify="required|password" placeholder="请输入密码" autocomplete="off" class="layui-input">
 </div>
 <div class="layui-form-mid layui-word-aux">*包含a_z、A_Z、1-9中的两种,且长度6-20</div>
 </div>
 <div class="layui-form-item layui-col-md4 layui-col-md-offset2">
 <label class="layui-form-label">手机号</label>
 <div class="layui-input-inline">
 <input type="text" name="mobile" th:value="${user.mobile}" lay-verify="required|phone" placeholder="请输入手机号" autocomplete="off" class="layui-input">
 </div>
 <div class="layui-form-mid layui-word-aux">*手机号</div>
 </div>
 <div class="layui-form-item layui-col-md4 layui-col-md-offset2">
 <label class="layui-form-label">昵称</label>
 <div class="layui-input-inline">
 <input type="text" name="nickname" th:value="${user.nickname}" lay-verify="required" placeholder="请输入昵称" autocomplete="off" class="layui-input">
 </div>
 <div class="layui-form-mid layui-word-aux">*不多于30个字符</div>
 </div>
 <div class="layui-form-item">
 <div class="layui-col-md4 layui-col-md-offset2">
 <label class="layui-form-label">头像</label>
 <div class="layui-input-inline">
 <button type="button" class="layui-btn" id="test1">
 <i class="layui-icon">&#xe67c;</i>上传图片
 </button>
 </div>
 </div>
 </div>
 <div class="layui-form-item layui-col-md-offset4">
 <div class="layui-input-block">
 <button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button>
 <button type="reset" class="layui-btn layui-btn-primary">重置</button>
 </div>
 </div>
</form>
<script>
 layui.use('form', function () {
 var form = layui.form, upload = layui.upload;
 form.render();
 Common.uploadFile('#test1', upload, function (data) {
 console.log(data);
 });
 //监听提交
 form.on('submit(formDemo)', function (data) {
 layer.msg(JSON.stringify(data.field));
 //TODO ajax提交表单
 return false;
 });
 });
</script>
</body>
</html>

verify.js

layui.use('form', function () {
 var form = layui.form;
 //自定义验证规则
 form.verify({
 username: function (value) {
 if (value.length < 6 || value.length > 12) {
 return '请输入6到12位的用户名';
 }
 }, password: function (value) {
 if (value.length < 4) {
 return '内容请输入至少4个字符';
 }
 }
 , phone: [/^1[3|4|5|7|8]\d{9}$/, '手机必须11位,只能是数字!']
 , email: [/^[a-z0-9._%-]+@([a-z0-9-]+\.)+[a-z]{2,4}$|^1[3|4|5|7|8]\d{9}$/, '邮箱格式不对']
 });
})

其他小技巧: idea使用thymeleaf模板时,页面取值总提示无法解析变量,但是又不影响实际应用,据说idea2017.3已经解决了,但是我现在用的2017.2,没有更新,但是同样可以解决。错误提示如图

波浪线提示.png

解决方法也很简单:File--settings--Editor--Inspections--Thymeleaf,去掉第一个校验即可。

去掉波浪线提示.png

本文分享自微信公众号 - 陌与尘埃(grq100296),作者:小尘哥

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 第22节 数组(Array)

    Go 语言提供了数组类型的数据结构。 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。

    小尘哥
  • 【springboot+easypoi】一行代码搞定简单的word导出

    小尘哥
  • 【springboot+easypoi】导出多个sheet页

    对,没有错,又是我,又是easyPOI,又是excel导出。每个程序猿都听说技术是为业务服务的,那么···当需求变了之后我们能做什么呢?

    小尘哥
  • layui修改 form表单的 长度

    Little JAVA
  • JFinal极速开发框架使用笔记(二) 两个问题,一个发现

    最近给新人出了一个小测试,我也用JFinal框架做了一下,记录一下使用过程中遇到的坑和新学到的知识点 首先是遇到的两个小问题, 一个是用最新版的eclipse运...

    二十三年蝉
  • Layui form 表单(常用)

    layui-form div.layui-form-item label.layui-form-label div.layui-input-block

    用户5760343
  • SSM框架结合LayUi文件上传模块接入COS对象存储服务

    在日常项目开发中经常会用到图片,视频等文件存储的操作,但是文件如果一直存放在本地服务器中,可以会导致资源浪费,且访问速度也有所限制,这时我们就会考虑CDN加速或...

    sr
  • MongoDB助力一个物流订单系统

    我们都知道MongoDB是一款非常出色的非关系型文档数据库,你肯定会想问MongoDB这么强,我们该怎么用或者有啥运用场景呢? MongoDB的应用场景非常多,...

    bigsai
  • 总结一下laravel中Hash::make()遇到的坑

    ==这里遇到的坑就是laravel框架中,每次hash的值都是不一致的,跟之前写过的md5不一样,md5是唯一的,但是只要保存进去了,就算hash以后的值是不一...

    一个淡定的打工菜鸟
  • layui响应式导航(菜单)

    今天来分享一套自己写的layui响应式导航栏菜单,网络上搜索无果,只能自己写了,现在分享出来。

    申霖

扫码关注云+社区

领取腾讯云代金券