vue+element+ts,原生js实现,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,
     }
}

好啦,有什么问题可以留言一起讨论~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值