この記事では主に、layui での動的データ テーブル ページングと静的データ テーブル ページングの実装について説明します。必要な方は参考にしてください。バックエンド プログラマとして、会社の機密データはすべて私たちの手にあるため、現時点では、会社のコア メンバーでない場合は、特定のデータにアクセスすることはできません。 PS から Linux まで、すべての作業は私たちの手で行う必要があります。幸いなことに、私たちはフロントエンド フレームワーク laui を発見し、私たちのプレッシャーを大幅に軽減しました。
今日は、まずlayui
が動的データ テーブル、静的データ テーブル、テーブル ページングを実装する方法を学びます。これには、データ テーブルの動的更新、データ テーブル ツールバーの使用、フォーム送信、その他の機能も含まれます。この静的ページングは情報 Web サイトにも適用できます。私の作業開発環境はdebian
デスクトップ バージョンなので、すべての実験もdebian
layui
实现动态数据表,静态数据表,以及表格的分页,其中还涉及到动态刷新数据表,数据表工具栏使用,表单提交等功能,这个静态分页同样适用在信息类网站,我的工作开发环境是debian
桌面版,所以所有的实验也是在debian
基础上测试
业务逻辑我都写到注释里面了,这样大家也友好一些,避免一会看代码,一会看说明容易分神
前端代码:
head.phtml(头文件代码)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title><?php echo $curTitle;?></title> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="format-detection" content="telephone=no"> <link rel="stylesheet" href="static/css/layui.css" media="all"> <link rel="stylesheet" href="static/css/globals.css" media="all"> <script src="static/layui.js" charset="utf-8"></script> <!--引入自定义模块全局配置文件--> <script src="static/global.js" charset="utf-8"></script> </head> <body class="layui-layout-body">
order_orderlist.phtml(主体业务代码)
<?php $this->import("head"); ?> <p class="layui-fluid"> <blockquote class="layui-elem-quote">注意:为保障访问速度,查询同时请配合时间范围,默认显示一天以内的记录</blockquote> <br/> <p class="layui-form-item layui-form-pane"> <p class="layui-inline"> <label class="layui-form-label" style="width: 85px;">商户号</label> <p class="layui-input-inline" style="width: 165px;"> <input type="text" name="merchant_no" autocomplete="off" class="layui-input"> </p> </p> <p class="layui-inline"> <label class="layui-form-label" style="width: 85px;">订单号:</label> <p class="layui-input-inline" style="width: 165px;"> <input type="text" name="order_no" autocomplete="off" class="layui-input"> </p> </p> <p class="layui-inline"> <label class="layui-form-label" style="width: 95px;">发起时间</label> <p class="layui-input-inline" style="width: 165px;"> <input type="text" class="layui-input" name="start_time" id="test5" placeholder="yyyy-MM-dd HH:mm:ss"> </p> <p class="layui-form-mid">-</p> <p class="layui-input-inline" style="width: 165px;"> <input type="text" class="layui-input" name="end_time" id="test6" placeholder="yyyy-MM-dd HH:mm:ss"> </p> </p> <p class="layui-inline"> <button id="fuck-btn" class="layui-btn layui-btn-normal" data-type="reload"><i class="layui-icon"></i>查询</button> <button id="reloadtable" class="layui-btn layui-btn-normal"><i class="layui-icon">ဂ</i>刷新数据</button> <button id="reloadpage" class="layui-btn layui-btn-normal"><i class="layui-icon">ဂ</i>刷新页面</button> </p> </p> <table class="layui-hide" id="test"></table> </p> <script> // 加载需要用到的模块,如果有使用到自定义模块也在此加载 layui.use(['laydate','form','table'], function(){ // 初始化元素,如果有大量的元素操作可以也引入和初始化element模块 var table = layui.table; var form = layui.form; var laydate = layui.laydate; var $ = layui.$; // 定义时间选择器 laydate.render({ elem:'#test5', type:'datetime' }); laydate.render({ elem:'#test6', type:'datetime' }); // 动态数据表渲染 table.render({ elem: '#test' /* 绑定表格容器id */ ,url:'index.php?c=orders&a=orderList' /* 获取数据的后端API URL */ ,where:{getlist:'orderlist'} /* 这里还可以额外的传参到后端 */ ,method: 'post' /* 使用什么协议,默认的是GET */ ,cellMinWidth: 60 /* 最小单元格宽度 */ ,cols: [[ {field:'orderno', title: '订单号',align: 'center',sort:true} ,{field:'username', title: '商户号',align: 'center'} ,{field:'user_orderno', title: '商户订单号',align: 'center'} ,{field:'trace_time', title: '创建时间',align: 'center',sort:true,width:200} ,{field:'price', title: '交易金额',align: 'center',sort:true} ,{field:'fee', title: '手续费',align: 'center',sort:true,width:80} ,{field:'real_price', title: '结算金额',align: 'center',sort:true} ,{field:'pay_type', title: '支付类型', align: 'center'} ,{field:'pay_status', title: '订单状态',align: 'center',width:90} ,{field:'pay_time', title: '支付时间',align: 'center',sort:true,width:200} ,{field:'push_nums', title: '通知次数',align: 'center',width:90} ,{field:'notice_result', title: '通知支付结果',align: 'center'} ]] // 使用sort将自动为我们添加排序事件,完全不用人工干预 ,page: true ,limit:10 ,id:'testReload' // 这里就是重载的id }); // 数据表重载,这个是配合上面的表格一起使用的 var active = { reload:function(){ table.reload('testReload',{ // 点击查询和刷新数据表会把以下参数传到后端进行查找和分页显示 where:{ merchant_no:$("input[name='merchant_no']").val(), order_no: $("input[name='order_no']").val(), start_time:$("input[name='start_time']").val(), end_time:$("input[name='end_time']").val() } }); } }; form.render(); // 渲染表单 // 查找点击时间,这里的事件绑定建议使用on来绑定,因为元素都是后期渲染过的 $("#fuck-btn").click(function(){ var type = $(this).data('type'); active[type] ? active[type].call(this) : ''; }); $("#reloadtable").click(function(){ active.reload(); }); $("#reloadpage").click(function(){ location.reload(); }); }); </script> </body> </html>
后端php代码
order.php(订单控制器,部分业务代码不用太深究)
// 订单列表 public function orderList() { // 动态渲染前台表格 $operating = $this->request->getPost('getlist', 'trim'); // 首次这里不会执行,数据表开始渲染的时候才会请求以下部分 if ('orderlist' === $operating) { // 进行分页查询 $page = $this->request->getPost('page', 'intval', 1); $limit = $this->request->getPost('limit', 'intval', 10); $start = ($page - 1) * $limit; // 如果有其他条件查询在这里可以带上 $merchant_no = $this->request->getPost('merchant_no', 'trim', ''); $order_no = $this->request->getPost('order_no', 'trim', ''); $start_time = $this->request->getPost('start_time', 'trim', date("Y-m-d H:i:s", strtotime("-1 day"))); $end_time = $this->request->getPost('end_time', 'trim', date("Y-m-d H:i:s"), time()); // 获取符合条件的记录数量 if($GLOBALS['SESSION']['admin_group_id'] >1){ $merchant_no = $GLOBALS['SESSION']['admin_username']; } $order_nums = orders::getItemNums($merchant_no, $order_no, $start_time, $end_time); // 分页进行查询条件记录 $order_list = orders::getItem($merchant_no, $order_no, $start_time, $end_time, $start, $limit); $datas = ['code' => 0, 'msg' => '']; // 将总的记录条数传给前台进行渲染分页 $datas['count'] = $order_nums; // 重新过滤一遍数据,很多没有用到的不能全部发给试图,尤其是动态渲染的,很容易暴露,建议加工一下再传 foreach ($order_list as $k => $v) { $order_list[$k]['orderno'] = $v['order_id']; $order_list[$k]['user_orderno'] = $v['order_no']; $order_list[$k]['username'] = $v['merchant_no']; $order_list[$k]['pay_type'] = ($v['pay_type'] == 1) ? "支付宝扫码" : "微信扫码"; $order_list[$k]['pay_status'] = ($v['callback_status'] > 0) ? "已支付" : "未支付"; $order_list[$k]['pay_time'] = $v['callback_time']; $order_list[$k]['notice_result'] = ($v['push_status'] > 0) ? "<span class=\"layui-badge layui-bg-blue\">已推送</span>" : "<span class=\"layui-badge layui-bg-gray\">未推送</span>"; } // 将数据通过json格式响应给前台渲染 $datas['data'] = $order_list; echo json_encode($datas); safe_exit(); } // 首次先现实模板页 self::$view->render('orders_orderlist'); }
数据格式请参照官方指导:数据接口格式,表格模块
调试的时候可以打开chrome
,firefox
的 console
和 network
进行查看,仔细研究分析
工具栏是指在行单元格内可以操作对应的行,因为使用layui
的元素监听,很容易就获取到相应对应整行的数据.
比如获取表单的数据,只需要监听表单提交事件,直接就可以一次获取到所有的参数和值:
<script> layui.use(['form','jquery'],function(){ let form = layui.form, $ = layui.$; form.on('submit(fuck-submit)', function(data){ if(data.field.password && data.field.password.length < 5){ layer.msg('密码不能小于5位'); return false; } $.post('index.php?&a=adminEdit&op=update&uid='+data.field.uid,{ username:data.field.username, password:data.field.password, level:data.field.level, is_enabled:data.field.is_enabled }, function(responseText){ //console.log(responseText); if(responseText.errno === 8){ layer.msg(responseText.errstr,{icon:6}); return false; } else { layer.msg(responseText.errstr,{icon:5}); location.reload(); } },'json' ); return false; }); }); </script>
这里是官方文档的:
form.on('submit(*)', function(data){ console.log(data.elem) //被执行事件的元素DOM对象,一般为button对象 console.log(data.form) //被执行提交的form对象,一般在存在form标签时才会返回 console.log(data.field) //当前容器的全部表单字段,名值对形式:{name: value} return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。 });
我们今天要操作的数据表也是要采用这种方式,首先我们看看看怎样生成和渲染出工具条:
只需要在body部分插入一个容器,注意这里的javascript
的type
是text/html
,这个是供layui
解析用的,在这里的d也就是我们在渲染表格的时候的数据,所有的字段的值都可以在这个d
里面获取到
<table class="layui-hide" lay-filter="fucktest" id="test"></table> <script type="text/html" id="barDemo"> <a class="layui-btn layui-btn-xs" user_id="{{d.admin_id}}" lay-event="edit">编辑</a> </script>
// 这里就是我们渲染表格字段的地方,和上面的容器进行绑定,容器里面可以通过d.fixed来获取到 {fixed: 'right', width:158,title:'操作', align:'center', toolbar: '#barDemo'}
然后我们就可以对工具条绑定事件了,这里我只使用了编辑事件
table.on('tool(fucktest)', function(obj){ //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值" var data = obj.data; //获得当前行数据 var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值) var tr = obj.tr; //获得当前行 tr 的DOM对象 if(layEvent === 'detail'){ //查看 //do somehing } else if(layEvent === 'del'){ //删除 layer.confirm('真的删除行么', function(index){ obj.del(); //删除对应行(tr)的DOM结构,并更新缓存 layer.close(index); //向服务端发送删除指令 }); } else if(layEvent === 'edit'){ //编辑 // 开始根据用户id来进行获取用户进入新窗口 var index = layer.open({ type: 2, title:'编辑管理员', area: ['700px', '560px'], maxmin: true, content: 'index.php?c=adminUser&a=editUser&uid='+data.admin_id }); layer.full(index); } })
这样在点击编辑之后就能激活对应的事件了,我们这里是打开新的一个全屏弹窗来修改管理员资料
在修改完成后,如果只是单纯的重载数据表可以使用我们前面使用的方式,如果是刷新页面直接使用location.reload()
// 重载数据表 var active = { reload:function(){ var demoReload = $("#demoReload"); var dateReload = $("#dateReload"); table.reload('testReload',{ where:{ username:demoReload.val(), dates:dateReload.val() } }); } }; $("#fresh-btn").click(function(){active.reload();}); $("#fresh-page-btn").click(function(){location.reload();});
这里是官方的例子 toolbar-绑定列工具条
toolbar 对应的模板,它可以存放在页面的任意位置:
<script type="text/html" id="barDemo"> <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 语法,如: --> {{# if(d.auth > 2){ }} <a class="layui-btn layui-btn-xs" lay-event="check">审核</a> {{# } }} </script> 注意:属性 lay-event="" 是模板的关键所在,值可随意定义。
渲染工具条:
table.render({ cols: [[ {field:'id', title:'ID', width:100} ,{fixed: 'right', width:150, align:'center', toolbar: '#barDemo'} //这里的toolbar值是模板元素的选择器 ]] }); 等价于: <th lay-data="{field:'id', width:100}">ID</th> <th lay-data="{fixed: 'right', width:150, align:'center', toolbar: '#barDemo'}"></th>
工具条绑定事件:
//监听工具条 table.on('tool(test)', function(obj){ //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值" var data = obj.data; //获得当前行数据 var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值) var tr = obj.tr; //获得当前行 tr 的DOM对象 if(layEvent === 'detail'){ //查看 //do somehing } else if(layEvent === 'del'){ //删除 layer.confirm('真的删除行么', function(index){ obj.del(); //删除对应行(tr)的DOM结构,并更新缓存 layer.close(index); //向服务端发送删除指令 }); } else if(layEvent === 'edit'){ //编辑 //do something //同步更新缓存对应的值 obj.update({ username: '123' ,title: 'xxx' }); } });
更加详细的介绍请仔细研读官方文档 layui table模块
在很多时候在pc
端过多的使用动态渲染不是一个明智的选择,比如稍微懂行的人都能看到你的API
和需要的param
,所以我们还是建议对安全要求比较高的程序上还是使用静态表格,通过模板引擎也好,还是直接使用使用后端动态语言混合,用户最终只能看到解析好的页面,对程序保护也是很有必要的,我的一个hacker
朋友在进行渗透的时候都是这样进行钻空子的
静态表格我这里直接是使用php
混合解析进行展示:
前端模板:
index.php
<?php $this->import('head');?> <body> <blockquote class="layui-elem-quote">注意:此处仅显示部分日志</blockquote> <table class="layui-table" lay-size="sm"> <colgroup> </colgroup> <thead> <tr> <th>日志ID</th> <th>操作用户</th> <th>操作</th> <th>控制器</th> <th>方法</th> <th>是否成功</th> <th>操作IP</th> <th>备注信息</th> <th>日期</th> </tr> </thead> <tbody> <?php foreach($log_list as $kk => $vv):?> <tr> <td><?php echo $vv['log_id'];?></td> <td><?php echo $vv['username'];?></td> <td><?php echo $vv['title'];?></td> <td><?php echo $vv['control'];?></td> <td><?php echo $vv['action'];?></td> <td><?php echo $vv['is_success'];?></td> <td><?php echo $vv['client_ip'];?></td> <td><?php echo $vv['remark'];?></td> <td><?php echo $vv['date'];?></td> </tr> <?php endforeach;?> </tbody> </table> <p id="test1"></p> <script src="js/layui/layui.js"></script> <script> layui.use('laypage', function(){ var laypage = layui.laypage; laypage.render({ elem: 'test1' //注意,这里的 test1 是 ID,不用加 # 号 ,count: <?php echo $log_num;?> // 数据总数,从服务端得到 ,curr: <?php echo $currpage;?> // 服务器端回传当前页 ,jump: function(obj, first){ //obj包含了当前分页的所有参数,比如: console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。 console.log(obj.limit); //得到每页显示的条数 //首次不执行,使用原始的curr,后面需要自己通过回传来更新 var curr = obj.curr; if(!first){ location.href='index.php?&a=adminLogList&page='+obj.curr; } } }); }); </script> </body> <?php $this->import('foot');?>
这里的原理非常简单,主要利用的是layui
下的laypage
模块,使用jump
public function adminLogList() { // 接收当前页,如果没有收到默认是第一页 $page = $this->request->getGet('page','intval',1); // 设置limit查找起始,DEFAULT_PER_PAGE为全局变量,设置的是每页显示10条 $start = ($page-1)*DEFAULT_PER_PAGE; // 获取总日志数量 $adminlog_num = adminLogs::getItemsNumber(); // 分页查找,其他查询条件暂时不传 $admin_log_list = adminLogs::getItems('','','','','',$start); $log_list = array(); foreach($admin_log_list as $kk => $vv){ if($vv['admin_id'] > 0){ try{ $admins = admins::getItemById($vv['admin_id']); $log_list[$kk]['username'] = $admins['username']; } catch (exception2 $e){ logexception($e->format_stack_trace()); } } else { $log_list[$kk]['username'] = 'Tourists'; } $log_list[$kk]['log_id'] = $vv['log_id']; $log_list[$kk]['control'] = $vv['control']; $log_list[$kk]['action'] = $vv['action']; $log_list[$kk]['is_success'] = $vv['is_success']; $log_list[$kk]['client_ip'] = ip2location($vv['client_ip']); $log_list[$kk]['remark'] = $vv['remark']; $log_list[$kk]['date'] = $vv['date']; $log_list[$kk]['title'] = $vv['title']; unset($admin_log_list[$kk]); } self::$view->setVar('currpage',$page); self::$view->setVar('log_num',$adminlog_num); self::$view->setVar('log_list',$log_list); self::$view->render('default_addloglist'); }
chrome
、 を開くことができます。Firefox
の console
と network
を確認し、注意深く調査して分析してください🎜layui
の要素監視を利用することで、グリッド内の対応する行を操作することで、該当するデータを簡単に取得することができます行全体。javascript
の type
は text/html
であることに注意してください。 layui
解析。ここでの d は、テーブルをレンダリングするときのデータです。この d
に含まれる値は 🎜rrreeerrreee🎜 になります。イベントをツールバーに追加します。ここでは編集イベント 🎜rrreee🎜 のみを使用して、[編集] をクリックした後に対応するイベントをアクティブにします。管理者情報を変更するための新しい全画面ポップアップ ウィンドウが開きます。location.reload()
を直接使用します。ツールバー: 🎜rrreee🎜 ツールバーバインディングイベント: 🎜rrreee🎜 より詳細な紹介については、公式ドキュメントのlayuiテーブルモジュールをよく読んでください🎜pc</ code> 側で動的レンダリングを過度に使用することは賢明な選択ではありません。たとえば、少しの知識があれば誰でも <code>API
と必要な param
を確認できるため、それでもお勧めします。比較的高いセキュリティ要件を持つプログラムは、テンプレート エンジンを使用するか、バックエンドの動的言語混合を直接使用するかにかかわらず、最終的には解析されたページのみを表示する必要があり、プログラムの保護も必要です。私の友人の code>hacker は、🎜🎜静的テーブルに侵入するときに、常にこのような抜け穴を利用します。ここでは、php
ハイブリッド解析を直接使用して、以下を表示します。layui
の下の laypage
モジュールを使用します。 code>jump でイベントをトリガーします🎜🎜🎜🎜adminLogList メソッド:🎜public function adminLogList() { // 接收当前页,如果没有收到默认是第一页 $page = $this->request->getGet('page','intval',1); // 设置limit查找起始,DEFAULT_PER_PAGE为全局变量,设置的是每页显示10条 $start = ($page-1)*DEFAULT_PER_PAGE; // 获取总日志数量 $adminlog_num = adminLogs::getItemsNumber(); // 分页查找,其他查询条件暂时不传 $admin_log_list = adminLogs::getItems('','','','','',$start); $log_list = array(); foreach($admin_log_list as $kk => $vv){ if($vv['admin_id'] > 0){ try{ $admins = admins::getItemById($vv['admin_id']); $log_list[$kk]['username'] = $admins['username']; } catch (exception2 $e){ logexception($e->format_stack_trace()); } } else { $log_list[$kk]['username'] = 'Tourists'; } $log_list[$kk]['log_id'] = $vv['log_id']; $log_list[$kk]['control'] = $vv['control']; $log_list[$kk]['action'] = $vv['action']; $log_list[$kk]['is_success'] = $vv['is_success']; $log_list[$kk]['client_ip'] = ip2location($vv['client_ip']); $log_list[$kk]['remark'] = $vv['remark']; $log_list[$kk]['date'] = $vv['date']; $log_list[$kk]['title'] = $vv['title']; unset($admin_log_list[$kk]); } self::$view->setVar('currpage',$page); self::$view->setVar('log_num',$adminlog_num); self::$view->setVar('log_list',$log_list); self::$view->render('default_addloglist'); }
最终效果,已经完成静态分页,此部分功能也适用于信息类网站:
相关推荐:
以上がlayui は動的および静的データテーブルのページングを実装します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。