用LayUI+AngularJs做一个帖子管理的功能

用LayUI+AngularJs做一个帖子管理的功能

首先。这是一个宝贝,让我爱不释手,并亲切的称之为后端之友。它遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用

没错就是LayUI ,官网: https://www.layui.com/

官方是这么描述的: 经典模块化前端框架

layui 是一款采用自身模块规范编写的前端 UI 框架。
遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到 API 的每一处细节都经过精心雕琢,非常适合界面的快速开发。layui 首个版本发布于2016年金秋,她区别于那些基于 MVVM 底层的 UI 框架,却并非逆道而行,而是信奉返璞归真之道。
准确地说,她更多是为服务端程序员量身定做,你无需涉足各种前端工具的复杂配置,只需面对浏览器本身,让一切你所需要的元素与交互,从这里信手拈来。

写一个类似帖子或者博文管理的功能。

一、一波需求

可以在主页以流式布局看所有的帖子, 还能把关于我的帖子们以表格方式呈现出来并可以对其增删改查。表格还有排序分页等常用功能。 

前端使用LayUI、jQuery

需求并不难。。myBatis很简单就可以实现。

演示:

二、一些实现细节

官网示例 上看,LayUI里面的组件是非常之丰富的,绝对可以应对一般网站的开发需求了。

而且 开发文档 写的也很明白,一定要认真看,不要上来就拿他们的实例直接CV,会出错。。

注意点:

  1. 你想用哪个功能模块,需要先引入layui/lay/modules 文件夹下对应的js文件。文档都有写,注意看。
  2. 从官网下好的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部分要做的事情:

  1. 从后端获取数据。
  2. 把表格渲染出来。
  3. 添上你自定义的工具列。

注意看代码中大量注释解释了字段或属性的作用。

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/

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注