naive ui的table组件自定义列拖拽功能

interface StateType {
	data: Array<RowData>;
	columns: any;//列可以在自己代码中自己自定义,
}
//下面的写法只是参考。
const state = reactive<StateType>({
	data: [],
	columns: computed(() =>
		createColumns({
			removeSingleRow(row: RowData, index) {
				//删除一行
				state.data.splice(index, 1);
			},
			createNextStage(row: RowData, index: number) {
				state.data.splice(index + 1, 0, {
					id: -1,
					name: "",
					cheif: [],
					startTime: null,
					endTime: null,
				});
				//重置id
				state.data = state.data.map((e, i) => {
					e.id = i;
					return e;
				});
				console.log("data", state.data);
			},
		})
	),
});
//是否开始拖动
const isDraggingStarted = ref(false);
const draggingRowIndex = ref(0);
const startY = ref(0);
const oldStartY = ref(0);
const throughIndex = ref(0);

//鼠标按下
const mouseDownHandler = function (e: any) {
	startY.value = e.clientY;
	const originalRow= e.target.parentNode;
	originalRow.style.cursor = "move";
	originalRow.style.userSelect = "none";

	const table = tableRef.value.$el;
	draggingRowIndex.value = [].slice
		.call(table.querySelectorAll("tr"))
		.indexOf(originalRow as never);

	throughIndex.value = draggingRowIndex.value;

	table.querySelectorAll("tr").forEach((row: any) => {
		row.style.position = "relative";
		row.style.transition = "transform ease .2s";
		row.style.transform = "translateY(0px)";
		row.style.zIndex = 0;
	});
	document.addEventListener("mousemove", mouseMoveHandler);
	document.addEventListener("mouseup", moveUpHandler);
};
//鼠标拖动
const mouseMoveHandler = function (e: any) {
	const table = tableRef.value.$el;
	const moveY = e.clientY - startY.value; //鼠标跟随Y
	if (draggingRowIndex.value === -1) {
		//未找到
		return;
	}
	const draggingRow: any = [].slice.call(table.querySelectorAll("tr"))[
		draggingRowIndex.value
	];

	const rect = draggingRow.getBoundingClientRect();
	const height = rect.height;
	draggingRow.style.position = "relative";
	draggingRow.style.zIndex = 9998;
	draggingRow.style.transform = `translateY(${moveY}px)`;
	draggingRow.style.transition = "unset";

	let direction = "";
	if (e.clientY < oldStartY.value) {
		//向上拖
		direction = "up";
	} else if (e.clientY > oldStartY.value) {
		//向下拖
		direction = "down";
	}
	const nextRowMoveDown = (
		rowIndex: number,
		translateY: number,
		callBack: () => void
	) => {
		const nextDownRow: any = [].slice.call(
			table.querySelectorAll(".n-data-table-tr")
		)[rowIndex];
		if (nextDownRow === undefined) {
			return;
		}
		const nextDownRowRect = nextDownRow.getBoundingClientRect();
		if (
			nextDownRowRect.top + nextDownRowRect.height - (rect.top + rect.height) <
			10
		) {
			nextDownRow.style.transform = `translateY(${translateY}px)`;
			callBack();
		}
	};
	const nextRowMoveUp = (
		rowIndex: number,
		translateY: number,
		callBack: () => void
	) => {
		const nextUpRow: any = [].slice.call(
			table.querySelectorAll(".n-data-table-tr")
		)[rowIndex];
		if (nextUpRow === undefined) {
			return;
		}
		const nextUpRowRect = nextUpRow.getBoundingClientRect();
		if (
			rect.top + rect.height - (nextUpRowRect.top + nextUpRowRect.height) <
			10
		) {
			nextUpRow.style.transform = `translateY(${translateY}px)`;
			callBack();
		}
	};
	if (draggingRowIndex.value === 1) {
		//拖拽第一列
		if (direction === "down") {
			nextRowMoveDown(throughIndex.value + 1, -height, () => {
				throughIndex.value = throughIndex.value + 1;
			});
		} else if (direction === "up") {
			nextRowMoveUp(throughIndex.value, 0, () => {
				throughIndex.value = throughIndex.value - 1;
			});
		}
	} else if (draggingRowIndex.value === state.data.length) {
		//拖拽最后一列
		if (direction === "down") {
			if (throughIndex.value < draggingRowIndex.value) {
				nextRowMoveDown(throughIndex.value + 1, 0, () => {
					throughIndex.value = throughIndex.value + 1;
				});
			}
		} else if (direction === "up") {
			nextRowMoveUp(throughIndex.value, height, () => {
				throughIndex.value = throughIndex.value - 1;
			});
		}
	} else {
		//拖拽中间列
		if (direction === "up") {
			//向上
			if (throughIndex.value === draggingRowIndex.value) {
				//中间第一次向上滑动
				nextRowMoveUp(throughIndex.value - 1, height, () => {
					throughIndex.value = throughIndex.value - 1;
				});
			} else if (throughIndex.value < draggingRowIndex.value) {
				//中间上方向上
				nextRowMoveUp(throughIndex.value - 1, height, () => {
					throughIndex.value = throughIndex.value - 1;
				});
			} else if (throughIndex.value > draggingRowIndex.value) {
				//中间下方向上
				nextRowMoveUp(throughIndex.value, 0, () => {
					throughIndex.value = throughIndex.value - 1;
				});
			}
		} else if (direction === "down") {
			//向下
			if (throughIndex.value === draggingRowIndex.value) {
				//中间第一次向下滑动
				nextRowMoveDown(throughIndex.value + 1, -height, () => {
					throughIndex.value = throughIndex.value + 1;
				});
			} else if (throughIndex.value < draggingRowIndex.value) {
				//中间上方向下
				nextRowMoveDown(throughIndex.value, 0, () => {
					throughIndex.value = throughIndex.value + 1;
				});
			} else if (throughIndex.value > draggingRowIndex.value) {
				//中间下方向下
				nextRowMoveDown(throughIndex.value + 1, -height, () => {
					throughIndex.value = throughIndex.value + 1;
				});
			}
		}
	}
	oldStartY.value = e.clientY;
};
//鼠标抬起
const moveUpHandler = function (e: any) {
	isDraggingStarted.value = false;
	startY.value = e.clientY;

	const table = tableRef.value.$el;
	if (throughIndex.value === draggingRowIndex.value) {
		//位置未发生偏移执行复位
		table.querySelectorAll(".n-data-table-tr").forEach((row: any) => {
			row.style.position = "relative";
			row.style.transition = "transform ease .2s";
			row.style.transform = "translateY(0px)";
			row.style.zIndex = 0;
		});
	} else {
		//固定拖拽之后的数据
		table
			.querySelectorAll(".n-data-table-tr")
			.forEach((row: any) => row.removeAttribute("style"));
		const elem = state.data.splice(draggingRowIndex.value - 1, 1)[0];
		state.data.splice(throughIndex.value - 1, 0, elem);
	}

	document.removeEventListener("mousemove", mouseMoveHandler);
	document.removeEventListener("mouseup", moveUpHandler);
};
<n-data-table
			ref="tableRef"
			:row-key="(row) => row.id"
			:columns="state.columns"
			:data="state.data"
			:min-height="500"
			:max-height="500"
		/>

仿照antd的table拖拽的效果,目前的代码还是有些不完善的地方,勉强可以用。 

https://ant.design/components/table-cn#components-table-demo-drag-sorting

naive ui参考文档

https://www.naiveui.com/zh-CN/os-theme/components/data-table

vue3文档路径

https://cn.vuejs.org/guide/introduction.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值