分页
使用
DataTables
插件来实现分页,还带有很多的特殊效果使用这个需要先引入
jQuery
的js
文件和与之相关的css
和js
分页分为:
- 客户端分页
- 优点:简单
- 缺点:数据多了,服务器加载慢、客户端加载慢、会崩溃
- 服务端分页
案例
这里拿一个文章列表显示作为案例
方式1
控制器查询文章列表并返回模板页面
public function index()
{
$data = Article::all();
return view('admin.article.index', compact('data'));
}
前端显示
<table class="table table-border table-bordered table-hover table-bg table-sort">
<thead>
<tr class="text-c">
<th width="80">ID</th>
<th width="100">文章标题</th>
<th width="130">加入时间</th>
<th width="100">操作</th>
</tr>
</thead>
<tbody>
@foreach ($data as $item)
<tr>
<td>{{ $item->id }}</td>
<td>{{ $item->title }}</td>
<td>{{ $item->created_at }}</td>
<td>
{{--这里就不写多详细了--}}
<a>编辑</a>
<a>删除</a>
</td>
</tr>
@endforeach
</tbody>
</table>
使用插件进行分页:
$('.table-sort').dataTable();
这样就一个初具规模的看似没毛病的分页就好了,加入有百万级别的数据这里就炸了。
优化
还是使用服务器端进行分页
不过这里使用插件的
ajax
请求来进行获取数据并进行分页和其他的设置
前端修改
<table class="table table-border table-bordered table-hover table-bg table-sort">
<thead>
<tr class="text-c">
<th width="80">ID</th>
<th width="100">文章标题</th>
<th width="130">加入时间</th>
<th width="100">操作</th>
</tr>
</thead>
</table>
这里将循环渲染的部分去掉。减少渲染的时间
js修改
插件的详细的个别有用的设置都在注释里进行说明
$('.table-sort').dataTable({
// 分页页数选择
lengthMenu: [5, 10, 15, 20, 25, 50, 100],
// 自带的搜索框 隐藏搜索
searching: false,
// 让索引为3的那一列不进行排序,这里为操作那一列
columnDefs: [
{targets: [3], orderable: false}
],
// 开启服务器端分页 开启ajax
serverSide: true,
// 进行ajax请求
ajax: {
// 请求地址
url: "{{ route('admin.article.index') }}",
// 请求方式
type: 'get',
},
// 指定每一列显示的数据
// {data: '表字段名称', defaultContent: '默认内容', className: '样式类'}
columns: [
{data: 'id', className: 'text-c'},
{data: 'title', className: 'text-c'},
{data: 'created_at', className: 'text-c'},
{data: 'action', defaultContent: '操作按钮', className: 'text-c'}
]
});
控制器实现
Laravel
没有TP
那样有一个request()->isAjax()
的判断操作所以会使用请求头中的
ajax
信息来判断这里使用
min
方法限制请求的个数,防止恶意使用postman
进行高额数量的请求造成服务器崩溃其他的
DataTables
插件需要返回的格式数据都进行了注释说明
public function index(Request $request)
{
if ($request->header('X-Requested-With') == 'XMLHttpRequest') {
// 开启位置
$start = $request->get('start', 0);
// 获取记录数 min => 防止恶意输入长串数据
$length = min(100, $request->get('length', 10));
// 获取数据
$data = Article::offset($start)->limit($length)->get();
// 记录总数
$total = Article::count();
$result = [
// draw: 客户端调用服务器端次数标识
'draw' => $request->get('draw'),
// recordsTotal: 获取数据记录总条数
'recordsTotal' => $total,
// recordsFiltered: 数据过滤后的总数量
'recordsFiltered' => $total,
// data: 获得的具体数据
'data' => $data,
];
return $result;
}
return view('admin.article.index');
}
在上述中,除了操作部分,基本都能进行显示内容,而编辑,删除这些按钮该如何显示呢?
还记得,
RBAC
那篇文章中,我们设计了一个Trait
来实现权限控制按钮的生成,那是使用访问器来实现的,这里,我们也使用访问器来实现操作那一列的显示:
{data: 'action', defaultContent: '操作按钮', className: 'text-c'}
,前端这里的data
说明了是数据表字段,但是真正的文章表里甚至别的表里,不存在action
这样的字段,所以我们通过模型的追加字段到Attribute
中,再配合访问器进行使用。
class Article extends Base
{
// 追加一个字段
protected $appends = ['action'];
/**
* 访问器实现追加字段操作的按钮实现
* @return string
*/
public function getActionAttribute()
{
return $this->editBtn('admin.article.edit').$this->deleteBtn('admin.article.destroy');
}
}
注意!
这里我们基础了
Base
基础模型,里面已经引入了Btn
Trait,所以文章模型里不需要再次引入,而不代表这里没有。
文章列表按钮显示dom方案显示
这里的意思是指
{data: 'aaa', defaultContent: '操作按钮', className: 'text-c'}
,data不再是action
的时候,使用回调函数进行渲染,这样也不建议这么玩。
$('.table-sort').dataTable({
// 分页页数选择
lengthMenu: [5, 10, 15, 20, 25, 50, 100],
// 隐藏搜索
searching: false,
columnDefs: [
{targets: [3], orderable: false}
],
// 开启服务器端分页 开启ajax
serverSide: true,
// 进行ajax请求
ajax: {
// 请求地址
url: "{{ route('admin.article.index') }}",
// 请求方式
type: 'get',
},
// 指定每一列显示的数据
columns: [
{data: 'id', className: 'text-c'},
{data: 'title', className: 'text-c'},
{data: 'created_at', className: 'text-c'},
{data: 'aaa', defaultContent: '操作按钮', className: 'text-c'}
],
// 回调方法
// row 当前行的dom对象
// data: 当前行的数据
// dataIndex: 当前行的数据索引
createdRow: function (row, data, dataIndex) {
// 行的最后一列
// console.log($(row).find('td:last-child'));
var td = $(row).find('td:last-child');
// 当前id号
var id = data.id;
// 显示的html内容
var html = `
<a href="/admin/article/${id}/edit" class="">修改</a>
<a href="/admin/article/${id}" class="delbtn">删除</a>
`;
// 把html添加到td中
td.html(html);
}
});