首先。这是一个宝贝,让我爱不释手,并亲切的称之为后端之友。它遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用。
没错就是LayUI ,官网: https://www.layui.com/
官方是这么描述的: 经典模块化前端框架
layui 是一款采用自身模块规范编写的前端 UI 框架。
遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到 API 的每一处细节都经过精心雕琢,非常适合界面的快速开发。layui 首个版本发布于2016年金秋,她区别于那些基于 MVVM 底层的 UI 框架,却并非逆道而行,而是信奉返璞归真之道。
准确地说,她更多是为服务端程序员量身定做,你无需涉足各种前端工具的复杂配置,只需面对浏览器本身,让一切你所需要的元素与交互,从这里信手拈来。
写一个类似帖子或者博文管理的功能。
一、一波需求
可以在主页以流式布局看所有的帖子, 还能把关于我的帖子们以表格方式呈现出来并可以对其增删改查。表格还有排序分页等常用功能。
前端使用LayUI、jQuery。
需求并不难。。myBatis很简单就可以实现。
演示:
二、一些实现细节
从 官网示例 上看,LayUI里面的组件是非常之丰富的,绝对可以应对一般网站的开发需求了。
而且 开发文档 写的也很明白,一定要认真看,不要上来就拿他们的实例直接CV,会出错。。
注意点:
- 你想用哪个功能模块,需要先引入layui/lay/modules 文件夹下对应的js文件。文档都有写,注意看。
- 从官网下好的zip解压后,直接把整个layui文件扔到项目下static静态资源目录下,不要想用哪个就复制哪个。
对于我这个功能首先肯定是先把流布局搞出来。。说到布局,LayUI也有自己栅格系统,个人感觉和BootStrap不相上下。 我这页面就是在container中写的。
<div class="layui-container">
<div class="layui-row">
<div class="layui-col-md9">
你的内容 9/12
</div>
<div class="layui-col-md3">
你的内容 3/12
</div>
</div>
移动设备、平板、桌面端的不同表现:
<div class="layui-row">
<div class="layui-col-xs6 layui-col-sm6 layui-col-md4">
移动:6/12 | 平板:6/12 | 桌面:4/12
</div>
<div class="layui-col-xs6 layui-col-sm6 layui-col-md4">
移动:6/12 | 平板:6/12 | 桌面:4/12
</div>
<div class="layui-col-xs4 layui-col-sm12 layui-col-md4">
移动:4/12 | 平板:12/12 | 桌面:4/12
</div>
<div class="layui-col-xs4 layui-col-sm7 layui-col-md8">
移动:4/12 | 平板:7/12 | 桌面:8/12
</div>
<div class="layui-col-xs4 layui-col-sm5 layui-col-md4">
移动:4/12 | 平板:5/12 | 桌面:4/12
</div>
</div>
</div>
然后写流加载,首先在点击进入主页面的按钮(方法)上,加一个ajax,我用的 AngularJs :
//先将将gotoBlog绑定在DOM元素上,然后:
app.controller( "con" , function ( $scope, $state, $http ) {
$scope.gotoBlog = function () {
$state.go('goBlogs');
$http({
url:'blogList',
method:'get',
params:{}
})
};
}
流式布局:这里面用到了一点ng的东西,就是为了方便循环遍历而已。
<!--博客区域 -->
<div>
<div id='warp'>
<div id="box">
<!-- 流加载博客 -->
<ul class="flow-default" id="LAY_demo2">
<li>
<loading-bar></loading-bar>
</li>
<%-- 这里用到了AngularJs 因为要从后端拿数据并遍历 --%>
<li class="contentt" ng-repeat="b in list">
<div class="blogMain">
<%--标题--%>
<p class="title" ng-bind="b.b_title">标题</p>
<%--信息--%>
<div class="blog-info" style="height: 25px;line-height: 17px">
<i class="fa fa-calendar-minus-o"></i>
<span ng-bind="b.b_creatDate">2018-03-03</span> <i>By</i><span ng-bind="b.b_author">User</span>
<i id="fuck" ng-click="fuck($event)" class="fa fa-heart-o"
style="cursor: pointer; margin-left: 20px;font-size: 16px"></i>
<span class="isNice"></span>
</div>
<p ng-bind="b.b_content" style="height: max-content">测试文字测试文字测试文字测试文字测试文字测试文字测试文字</p>
</div>
</li>
</ul>
</div>
</div>
</div>
js:
layui.use('flow', function () {
var flow = layui.flow;
flow.load({
elem: '#LAY_demo2' //流加载容器
, scrollElem: '#LAY_demo2' //滚动条所在元素,一般不用填,此处只是演示需要。
, isAuto: false
, isLazyimg: true
, done: function (page, next) { //加载下一页
//模拟插入
setTimeout(function () {
var lis = [];
for (var i = 0; i < 3; i++) {
lis.push('<li ng-repeat="b in list">\n' +
' <div class="blogMain" >\n' +
' <%--标题--%>\n' +
' <p class="title" ng-bind="b.b_title">心得体会</p>\n' +
' <%--信息--%>\n' +
' <div class="blog-info" style="height: 25px;line-height: 17px">\n' +
' <i class="fa fa-calendar-minus-o"></i><span ng-bind="b.b_creatDate">2018-04-22</span> <i>By</i>\n' +
' <span ng-bind="b.b_author" >User</span>\n' +
' <i class="fa fa-heart-o" style="cursor: pointer; margin-left: 20px;font-size: 16px"></i>\n' +
' <span class="isNice"></span>\n' +
' </div>\n' +
' <p ng-bind="b.b_content" style="height: max-content">\n' +
' 当我在工作中遇到挫折的时候,我会问自己一句话!!““难道没有别的方法能够解决了吗””!!(不妨自己去试一下)那样会更好的激发出你的潜力,敢于去应对现实。确实有的时候很委屈,很不服。但是你回头想想,我为什么会不服。一是:性格问题,我就不服这个事情;二是:我不服的就是,别人能做到,其实我也能做到;有个节目叫《挑战主持人》上面有句话说的个性的经典:“也许你不服,但你被淘汰了”难道在那个节目上的选手差距很大吗不!其实都是平等的,谁把自己的才能发挥的淋漓尽致谁就不会被淘汰。回头看看自己,在你的群体中,你自己是在一个什么位置。不要把自己看的太厉害,那样你会“悄然走开”也不要把自己看的太没用,那样你会“猪狗不如”凡事都要把心态摆正,根据自己的状况去做自己该做的事情,如果这个事叫我去做,我会去怎样做;先在自己心中摆个谱子。去做的时候你就不会“不卑不亢”机会都是留给有准备的人!</p>\n' +
' </div>\n' +
' </li>')
}
next(lis.join(''), page < 3);
}, 500);
}
});
});
样式不贴了。一人一个喜好。。我比较喜欢半透明磨砂玻璃的感觉。
然后感觉页面干巴巴的少点什么,又加了一个轮播图:
<!--轮播图-->
<div class="layui-carousel" id="LB1">
<div carousel-item="">
<div><img src="imgs/blog/L3.jpg" alt=""></div>
<div><img src="imgs/blog/L4.jpg" alt=""></div>
<div><img src="imgs/blog/L1.jpg" alt=""></div>
</div>
</div>
JS:
layui.use('carousel', function () {
var carousel = layui.carousel;
//建造实例
carousel.render({
elem: '#LB1'
, width: '657px' //设置容器宽度
, arrow: 'always' //始终显示箭头
, anim: 'updown' //切换动画方式
});
});
很简单。
然后点击发表按钮,会弹出一个模态框,里面有一个富文本编辑器:
<button id="saveBlog" class="layui-btn layui-btn-lg" style=" left:33px;">发表</button>
JS里面用到了各种弹出层和富文本编辑器以及取值代码。
jQuery(function () {
//点击发帖弹出一个页面层
jQuery('#saveBlog').on('click', function () {
layer.open({
title: '发表', //弹出标题
type: 1, //0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
area: ['900px', '550px'],
shadeClose: false, //点击遮罩关闭
content: '<div style="padding:20px;margin-top: 20px">' +
'<div class=\'select_overlay\'>\n' +
' <div style=\' width: 50px;margin: 215px auto;\' class=\'load\'>\n' +
' <i style=\'font-size: 35px\' class=\'fa fa-refresh fa-spin\'></i>\n' +
' </div>\n' +
' </div><div>' +
' <input style="color: black" type="text" name="title" required lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input">' +
'</div>' +
'<textarea id="blogTest" style="display: none;" >在此输入内容...</textarea> ' +
' <button style="margin-top: 10px;" data-type="content" id="submt" class="layui-btn layui-btn-normal">发表</button>',
yes: function () {
}
});
// 注意构建富文本必须在弹窗后边
layui.use('layedit', function () {
var layedit = layui.layedit
, aaa = layui.jquery;
//构建一个默认的编辑器
var index = layedit.build('blogTest');
//编辑器外部操作
var active = {
content: function () {
console.log("文本" + layedit.getContent(index)); //获取编辑器内容
console.log("标题" + jQuery('.layui-input').val());
console.log("标题" + jQuery('.layui-input').val());
var myDate = new Date();
var year = myDate.getFullYear();
var month = myDate.getMonth() + 1;
var date = myDate.getDate();
var h = myDate.getHours();
var m = myDate.getMinutes();
var s = myDate.getSeconds();
var now=year+'-'+getNow(month)+"-"+getNow(date)+" "+getNow(h)+':'+getNow(m)+":"+getNow(s);
let blog = {};
blog.b_author = 'admin';
blog.b_title = jQuery('.layui-input').val();
blog.b_creatDate = now;
blog.b_content = layedit.getContent(index);
blog.b_titleIMG = 'none';
let xhr2 = {
type: "Post",
url: "saveBlog",
data: {
"blogJson": JSON.stringify(blog)
},
dataType: 'json', //定义type后,后端传来的数据必然是josn类型,否则报错
timeout: "3000",
beforeSend: function () {
jQuery(".select_overlay").css('display', 'block');
},
complete: function () {
jQuery(".select_overlay").css('display', 'none');
},
success: function (data) {
if (data == 1) {
layer.msg('成功!', {
icon: 1,
time: 1500 //2秒关闭(如果不配置,默认是3秒)
}, function () {
layer.closeAll();
});
setTimeout(function () {
window.location.reload();
}, 500)
} else {
layer.msg('失败!', {
icon: 2,
time: 1500 //2秒关闭(如果不配置,默认是3秒)
}, function () {
layer.closeAll();
});
}
},
error: function (data) {
alert("错误" + data);
}
};
jQuery.ajax(xhr2);
function getNow(s) {
return s < 10 ? '0' + s : s;
}
}
, text: function () {
console.log(layedit.getText(index)); //获取编辑器纯文本内容
}
, selection: function () {
console.log(layedit.getSelection(index));
}
};
//点击提交的事件
aaa('#submt').on('click', function () {
var type = aaa(this).data('type');
active[type] ? active[type].call(this) : '';
});
});
});
到这里,首页中关于Layui核心代码就齐了,其他的排版布局啥的就不贴了。都是些基础前端代码。
然后看表格
官方的表格文档写的非常详细。 戳我去看
我只领教了一些皮毛,但我感觉这些皮毛就已经省了好大的代码量,尤其是分页。
首先要先写一个<table>标签作为入口:
<table id="blogs" lay-filter="blogTable"></table>
还需要一个用于操作表格的工具列。比如详情、编辑、删除操作:
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-primary 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>
</script>
JS部分要做的事情:
- 从后端获取数据。
- 把表格渲染出来。
- 添上你自定义的工具列。
注意看代码中大量注释解释了字段或属性的作用。
layui.use('table', function(){
var table = layui.table;
//从后端获取数据并渲染到页面
table.render({
elem : '#blogs', //绑定DO元素,就table标签的id
url : 'layUIlist' //数据接口, 即 @WebServlet("/tables")或@RequestMapping( value="/tables"), 注意不要带'/'
,width : '1000' //表格width900px
,limit:10 //每页十条数据
,page : true //开启分页
,cols : [ [ //表头
//!!!!注意这里的field 字段!!!!
//名字必须和传过来的DTO类中还有User类的属性名字一致!!!
{
field : 'b_id',
title : 'ID', //设定标题名称
sort : true, //是否开启本列排序
fixed : 'left', //固定列。可选值有:left(固定在左)、right(固定在右)。一旦设定,对应的列将会被固定在左或右,不随滚动条而滚动。
width : 80
}, {
field : 'b_author',
title : '作者',
width : 100, //自定义文本,如空数据时的异常提示等。注:layui 2.2.5 开始新增。
text :"no data"
}, {
field : 'b_title',
title : '标题',
//sort: true - 开启本列排序
edit : text, //单元格编辑类型(默认不开启)目前只支持:text(输入框)
}
, {
field : 'b_creatDate',
title : '创建日期',
sort : true,
}, {
fixed : 'right',
align : 'center',
toolbar : '#barDemo', // 注意: 这里的toolbar值是模板元素的选择器。上面写了<script type="text/html" id="barDemo">
}
] ],
text : {
none : '暂无相关数据' //默认:无数据。注:该属性为 layui 2.2.5 开始新增
}
});
//监听工具条,点击会出现对应的自定义事件
table.on('tool(blogTable)', function(obj){
var data = obj.data;
if(obj.event === 'detail'){
layer.msg( data.b_content ); //弹出一个小提示框
} else if(obj.event === 'del'){
layer.confirm('确定删除?', function(index){
obj.del();
layer.close(index);
});
} else if(obj.event === 'edit'){
layer.open({ //开启一个模态框
title:"修改",
shadeClose: true,
type: 1, //不同数字代表不同类型模态框,具体看文档
skin: 'layui-layer-rim', //类样式。可以直接用这个类名写SCC样式,在这里我加了边框
area: ['400px', '500px'], //宽高
content: '<textarea class="layui-textarea" style="color: black;height: 445px;" >'+data.b_content+'</textarea>',
btn:['确认'], //自定义按钮
yes:function () { //回调函数
layer.close(0);
}
});
}
});
jQuery('.demoTable .layui-btn').on('click', function(){
var type = jQuery(this).data('type');
active[type] ? active[type].call(this) : '';
});
});
注意LayUI强制要求的数据格式:
let jsons = {
"code": 0,
"msg": "你随便写",
"count": 20, //这是总数据量
"data": [{ //每页显示的数据
"b_id": 10000,
"b_title": "模拟标题1",
"b_date": "2019-2-11",
}, {
"b_id": 10000,
"b_title": "模拟标题2",
"b_date": "2019-5-11",
}, {
"b_id": 10000,
"b_title": "模拟标题3",
"b_date": "2019-11-13",
}]
}
到这涉及到了LayUI发送的数据请求格式了,拿我这里举例,F12看下网络 :
注意红框的请求:page=1&limit=10
即他这次请求的是:数据分页第一页,包含10条数据。
当我点表格中下一页的按钮,发出请求: page=2&limit=10
当我点表中中每页显示20条数据,发出请求:page=1&limit=20
这就等于直接把Sql的分页参数直接告诉你。
这就非常简单了。
先定义一个json传输对象:
/**
* 表格传输对象
*/
@Getter
@Setter
public class BlogListDTO {
private String code; //
private String msg; //应该是后台返回的消息
private String count; //数据总数
private List<Blog> data;//单页的数据
public BlogListDTO(String msg , List<Blog> list ,String count ){
this.code ="0";
this.msg = msg;
this.count = count;
this.data = list;
}
}
在后台的mappe接口中写一个方法:
/**
* 返回当前页的Blogs
* @param currentPage 当前页
* @param limit 每页条数
* @return List<Blog> 查到的BlogList
*/
List<Blog> getLimit( @Param("currentPage") Integer currentPage ,@Param("limit") Integer limit );
mapper接口实现下:
<select id="getLimitBlogs" resultType="com.lzm.entity.Blog">
SELECT
b_id, b_title, b_content, b_author, b_creatDate
from
blog
limit #{currentPage},#{limit};
</select>
在控制层获取下数据:
String page = req.getParameter("page");
String limit = req.getParameter("limit");
然后调用刚写好的getLimit()方法。 封装进BlogListDTO对象中。
转成Json格式返给前台,搞定收工。
三、总结
平心而论LayUI这一套东西我是真的喜欢。使用简单,而且UI界面设计的也很符合我口味。不熟练的话,多用用就好了。
里边同样也有很多坑。
比如Layui的一些函数,会把jQuery的$符干掉。。导致总会出现一些诡异的属性找不到的错误。。 ,导致后来我干脆用jQuery代替$。
还有LayUI的Vue共同使用的话,会出现一些不兼容的问题,我已经踩了几个了,,这些坑放到下次写。
以上。
转载请标明出处:
http://lzyz.fun/layuiblog/