vue+element+ts,原生js实现,table表格组件自定义拖拽列
需求:因为表格列太多,看后边字段不方便,所以想添加一个自定义列的功能,不想看见某列也可以设置隐藏效果:拖动右边的列名,table列会随着移动实现:首先把写成动态的
·
需求:因为表格列太多,看后边字段不方便,所以想添加一个自定义列的功能,不想看见某列也可以设置隐藏
效果:拖动右边的列名,table列会随着移动(列隐藏功能这次没写)
实现:
首先把el-table-column写成动态的(我的表格数据tableData是后台返的数据,列名是前端写的)
<el-table :data='tableData' row-key="goods_id"> //row-key必须要加,不然列可能会错位
<el-table-column
v-if='tableData.length>0' //等数据请求回来再渲染
v-for="(item, index) in colData" //colData默认的列排序
:key="`colData_${index}`"
:prop="colData[index].props"
:label='item.title'
:fixed='item.key == "0"' //动态固定某列
:width='item.width' //列宽度
>
</el-table-column>
</el-table>
//全局变量里
colData: [
{ width:300,props:'action',key:'0',title: '操作', isShow: true,checked:true },
{ width:120,props:'goods_name',key:'0',title: '商品名称', isShow: true,checked:true },
{ width:120,props:'goods_id',key:'1',title: '商品ID', isShow: true,checked:false },
{ width:120,props:'goods_pricerange',key:'2',title: '价格(元/件)', isShow: true,checked:false },
{ width:120,props:'goods_state_label',key:'3',title: '状态', isShow: true,checked:false },
{ width:120,props:'goods_storage',key:'4',title: '库存', isShow: true ,checked:false},
{ width:120,props:'goods_image',key:'5',title: '商品图片', isShow: true,checked:false },
{ width:120,props:'goods_full_image',key:'6',title: '商品原图', isShow: true,checked:false },
{ width:150,props:'last_image_update_time',key:'7',title: '图片更新时间', isShow: true,checked:false },
{ width:120,props:'goods_flag_img',key:'8',title: '角标', isShow: true,checked:false },
{ width:120,props:'is_assess_video',key:'9',title: '是否含测评视频', isShow: true ,checked:false},
{ width:120,props:'assess_video_time',key:'10',title: '视频上传时间', isShow: true,checked:false },
{ width:120,props:'is_fruit_box_label',key:'11',title: '是否含筐', isShow: true,checked:false },
{ width:120,props:'gc_id',key:'12',title: '分类ID', isShow: true,checked:false },
{ width:180,props:'gc_name',key:'13',title: '分类名称', isShow: true,checked:false },
{ width:120,props:'goods_producingname',key:'14',title: '产地', isShow: true,checked:false },
{ width:120,props:'goods_grade',key:'15',title: '等级', isShow: true ,checked:false},
{ width:120,props:'store_id',key:'16',title: '店铺ID', isShow: true,checked:false },
{ width:120,props:'store_name',key:'17',title: '店铺名称', isShow: true,checked:false },
{ width:120,props:'is_own_shop',key:'18',title: '店铺类型', isShow: true,checked:false },
{ width:120,props:'assess_update_time',key:'19',title: '测评更新时间', isShow: true,checked:false },
{ width:120,props:'assess_user_name',key:'20',title: '测评更新人', isShow: true,checked:false },
{ width:150,props:'goods_edittime',key:'21',title: '编辑时间', isShow: true,checked:false },
{ width:120,props:'goods_number',key:'22',title: '规格', isShow: true,checked:false },
{ width:120,props:'goods_sizing',key:'23',title: '果径(mm)', isShow: true,checked:false },
{ width:120,props:'goods_volume',key:'24',title: '包装体积', isShow: true,checked:false },
],
但是呢,可能某列会有其他操作,不仅仅是展示数据这么简单,所以这时候可以用插槽来实现。比如我的商品名称颜色是不一样的
//因为列现在是数组渲染的,所以v-if判断一定要有,不然每个列都会多一个插槽
//商品名称插槽
<template #default='scope' v-if="colData[index].props == 'goods_name'">
<div :style="{ color: scope.row.is_red == 1 ? '#F04134' : '#777777' }">{{ scope.row.goods_name }}</div>
</template>
再比如我的商品图片是鼠标移入放大的效果
//商品图片插槽
<template v-if="colData[index].props == 'goods_image'" #default='scope'>
<el-popover placement='left' title='' trigger='hover'>
<img :src='scope.row.goods_image' style='width:220px;height:220px'>
<template #reference>
<img :src='scope.row.goods_image' style='width:60px;height:60px;max-height: 60px; max-width: 130px'>
</template>
</el-popover>
</template>
好,开始主要内容,右边的设置icon,鼠标移入div显示,拖拽效果使用原生js来实现,首先最重要的是transition-group标签来实现动画,给transition-group的属性name设为‘sort’,并在style里设置
.sort-move {
transition: transform 0.3s;
}
<div class='col_set'>
<i class="el-icon-setting" style='font-size: 24px;color: #409eff' @mouseenter='onEnter'></i>
</div>
//*<transition-group>标签
<div class='col_div' v-show='colShow == 1' @mouseleave="onLeave">
<div class='col_content'>
<span style='width: 100%;text-align: center;line-height: 40px;border-bottom: 1px solid #E4E4E4;'>可拖动改变列表顺序</span>
<transition-group class='col_list' @dragover="dragover()" name="sort">
<ul class='col_ul' v-for="i in colData.filter(item => item.key !== '0')" //因为我的操作和商品名称是固定列,不可拖动,所以我在这里处理了
:draggable="true"
:label="i.title"
:key="i.key"
@dragstart="dragstart(i)"
@dragenter="dragenter(i)"
@dragend="dragend(i)">
<i class="el-icon-menu tip" style='font-size: 16px;color: #999999'></i>
{{i.title}}
</ul>
</transition-group>
</div>
</div>
//ts语法
export default {
setup() {
const state: any = reactive({
colShow:0, //是否显示
oldVal: 0, //旧数据
newVal: 0, //拖拽后的新数据
})
//鼠标移入div显示
const onEnter= () =>{
state.colShow = 1
};
//鼠标离开
const onLeave= () =>{
state.colShow = 0
};
// 拖动事件(主要是为了拖动时鼠标光标不变为禁止)
const dragover= (e: any) =>{
e.preventDefault()
}
//开始拖动
const dragstart = (val)=> {
state.oldVal = val;
};
//拖动过程
const dragenter = (val)=> {
state.newVal = val;
};
//拖动结束
const dragend = (value: any, e: any)=> {
if (state.oldVal !== state.newVal) {
let oldIndex = state.colData.indexOf(state.oldVal)
let newIndex = state.colData.indexOf(state.newVal)
let newItems = [...state.colData]
// 删除老的节点
newItems.splice(oldIndex, 1)
// 在列表中目标位置增加新的节点
newItems.splice(newIndex, 0, state.oldVal)
state.colData = [...newItems]
localStorage.setItem('colDatalist',JSON.stringify(state.colData) )
}
};
return {
onEnter,
onLeave,
dragstart,
dragenter,
dragover,
dragend,
}
}
好啦,有什么问题可以留言一起讨论~
更多推荐
已为社区贡献5条内容
所有评论(0)