您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
虚拟数据填充及同一页面多个分页问题(laravel11+inertia+Element plus分页组件的使用)
发布时间:2024-11-09 20:50:00编辑:雪饮阅读()
-
说到虚拟数据填充,其实这里用到了Eloquent模型中的$fillable属性。
就是当你没有定义$fillable,则Eloquent模型会保护数据库中的所有字段。
$userTask=\App\Models\UserTask::create([
"a"=>"av",
"b"=>"bv"
]);
比如说这样的赋值操作。
它就会报错如
Add [a] to fillable property to allow mass assignment on [App\Models\UserTask].
因为字段a并没有定义为可赋值的列表中。
那么你只能手动来指定该字段,给模型的实例属性a进行手动赋值,而不是统一用数组来进行自动赋值。
那么除非你的模型中定义了如
protected $fillable = ['a'];
那么create会直接insert到数据库的。
那么接下来我们了解下虚拟数据填充,其实我们之前不是有个param的字段,但是由于是json编码后存储的,那么我们假如在数据列表中也需要展示出来,除了传统的赋值,也可以对fillable进行操作,为什么说是虚拟数据呢,我认为是这个我可以别名的,数据库中未必有这个字段。
例如我模型中定义fillable如
protected $fillable = ['paramObject'];
那么我得到数据列表的数据后可以遍历填充
foreach($tasks as $key=>$val){
$val->fill(["paramObject"=>json_decode($val->param)]);
}
然后再扔给前端,前端就包含了这个paramObject对象,并且已经是json对象,而不是json字符串了。
那么我前端之前的jobId字段展示的el-table的column栏位则可以修改如
<el-table-column label="Job">
<template v-slot="scope">
<template v-if="scope.row.type == 1">
<el-table :data="ChildDate(scope.row)" border>
<el-table-column prop="job_id" label="JobId" />
<el-table-column prop="typeFormat" label="Type" />
<el-table-column prop="paramObject.subject" label="Subject" />
<el-table-column prop="paramObject.body" label="Body" />
<el-table-column prop="paramObject.sendTime" label="SendTime" />
</el-table>
</template>
</template>
</el-table-column>
注意到我们这里使用了el-table的嵌套,所以数据源上面需要将单条数据对象也转换为数组形式,所以要实现子数据源的处理函数如
const ChildDate=(row)=>{
if(row.type==1){
row.typeFormat="SendEmail";
}
return [row];
}
另外就是上篇中我们不是做了el-table的进一步封装,其实在里面还有一个问题,就是父组件对于AllUserTask的el-tab-pane里面没有传递可以被$emit的事件。
好像即便是传递了也会在控制台有警告信息。
那么首先要做的就是传递上
<el-tab-pane label="AllUserTask" name="AllUser">
<Tasktable :tasks="tasks" @deleteFunc="deleteFunc" />
</el-tab-pane>
其次就是在封装的table组件中也声明下emit将要抛出的事件。
defineEmits(['deleteFunc'])
那么接下来咱们要说的就是同一页面分页问题了,所谓同一页面分页其实就是页面不会改变咯。
那么我们封装的table组件就需要再次加入分页组件了,这里也是采用element plus的分页组件。虽然我目前element plus 2.8.7的时候该分页组件仍旧有提示一些事件即将废弃。
<div class="example-pagination-block">
<el-pagination layout="prev, pager, next" :total="total" :page-size="pageSize" :default-current-page="current_page" @change="pageChange"/>
</div>
这里分页组件我们调用了总数据条数,分页大小,当前页,页码改变的事件
那么对于前三个属性我们需要父组件传递给我们
const props=defineProps(['tasks','pageSize','total','current_page']);
而页码改变的事件我们需要emit父级的事件
var emit=defineEmits(['deleteFunc','pageChange'])
const pageChange=(param_currentPage,param_pageSize)=>{
emit("pageChange",param_currentPage);
}
那么接下来咱们user task列表组件调用刚才封装的table组件就需要给这四个属性/事件提供支持
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick" @tab-change="handleChange" :before-leave="beforeLeave">
<el-tab-pane label="AllUserTask" name="AllUser">
<Tasktable :tasks="taskData.data" :pageSize="taskData.per_page" :total="taskData.total" :current_page="taskData.current_page" @deleteFunc="deleteFunc" @pageChange="pageChange" />
</el-tab-pane>
<el-tab-pane label="CurrentUserTask" name="CurrentUser">
<Tasktable :tasks="taskData.data" :pageSize="taskData.per_page" :total="taskData.total" :current_page="taskData.current_page" @deleteFunc="deleteFunc" @pageChange="pageChange" />
</el-tab-pane>
</el-tabs>
这里可以看到由原来的tasks修改为taskData是因为现在不纯是数据列表,还包含分页信息。
所以index.vue中的props需要重新定义下
const props=defineProps(['taskData','type','pageSize']);
那么接下来我们既要响应下table组件的页码变化以获取对应页码的数据,并且我们还得关联上之前的tab当前的选中情况,所以实现的页码改变事件如
const pageChange=(newPage)=>{
let visitObject={
method: 'get',
data: {page:newPage,type:activeName.value},
replace: false,
preserveState: false,
preserveScroll: false,
only: [],
headers: {},
errorBag: null,
forceFormData: false,
onCancelToken: cancelToken => {
},
onCancel: () => {
},
onBefore: visit => {
},
onStart: visit => {
},
onProgress: progress => {
},
onSuccess: page => {
console.log("page",page);
},
onError: errors => {
},
onFinish: visit => {
},
}
router.visit(route('user_task.index'),visitObject)
}
那么既然现在的user task是包含分页信息了,所以user task控制器中的index方法则也需要对应实现
public function index(Request $request){
$type=$request->input("type",'AllUser');
$pageSize=$request->input("pageSize",2);
$tasks=\App\Models\UserTask::where(function($query) use($type,$request){
if($type=="CurrentUser"){
$query->where("uid",$request->user()->id);
}
})->orderBy("id","desc")->paginate($pageSize);
foreach($tasks as $key=>$val){
$val->fill(["paramObject"=>json_decode($val->param)]);
}
return Inertia::render('UserTask/Index',[
'taskData'=>$tasks,
'type'=>$type
]);
}
那么最后进行分页请求测试看看

这里可以看到我们请求筛选是直接all,也即是没有筛选,并且是一个xhr请求,所以这里页面并没有改变。这样以来就解决了同一页面多个分页问题。当然多个分页还有一种情况就是两个分页组件咯。其实道理上都是差不多的,最简单粗暴的就是以上数据都来两份。最麻烦的就是抽象出公共部分进行处理。
本期词汇
eloquent 雄辩的,口才流利的
emit 发出(声音或噪音)
pagination 标记页数;页码
关键字词:laravel11,inertia,element plus,分页
相关文章
- 列出当前用户的所有Task(laravel11集成Element plus T
- 删除Task相关的逻辑及权限验证(laravel11中的事务与针
- TaskController重构到repo中(解决队列的delay无效问题
- 编辑Task相关的数据验证及权限(laravel11队列关联用户
- Task编辑保存相关的逻辑(laravel11表单请求的验证消息
- Task标记完成的逻辑、新建Task相关的数据验证及权限(la
- 新建项目的数据验证(基于laravel11+inertia的数据验证
- laravel中的一对多关系使用与inertia的link使用
- 列出已有项目分类(laravel11+breeze+inertia实现增与
- 图片上传保存逻辑(laravel11+breeze+inertia+vue3实现