Lista de clasificación de arrastrar y soltar en Vue3

El contenido principal de este trabajo se divide en tres partes. Primero, escribí la función de arrastrar y ordenar la lista a mano en Vue3 usando HTML5el atributo. draggableA continuación, registra cómo arrastrar y ordenar los componentes de la tabla en combinación con Element Plusla biblioteca de componentes . La última parte es el uso de componentes de arrastrar y soltar.sortable.jsel-tablevuedraggable

Este artículo está basado en su pila de tecnología Vite.Vue3Element Plus

implementos arrastrables clasificación de arrastrar y soltar

propiedades y eventos

draggableLos atributos son nuevos atributos arrastrables en HTML5.

En HTML, a excepción de las imágenes, los enlaces y el texto seleccionado que se pueden arrastrar de forma predeterminada, otros elementos no se pueden arrastrar de forma predeterminada. Si desea que otros elementos se puedan arrastrar, primero debe draggableestablecer la propiedad en true.

<p draggable="true"> 可拖拽</p>
复制代码

Una vez completada la configuración, es necesario combinar algunos eventos para completar el proceso de arrastrar y soltar:

  • Eventos para arrastrar elementos
evento temporización del disparador
dragstart Ejecutado una vez cuando comienza el arrastre
drag Se activa varias veces después de que comienza el arrastre
dragend Activado 1 vez después de arrastrar
  • Eventos que pueden soltar objetivos
evento temporización del disparador
dragenter Ejecutado una vez al arrastrar un elemento a un objetivo que se puede soltar
dragover Se activa varias veces al arrastrar un elemento a un destino que se puede soltar (una vez cada 100 milisegundos)
drop Cuando el elemento arrastrado se suelta en el destino que se puede soltar (este evento solo tendrá efecto si se establece el arrastre)

objetivo colocable

dragenter o  dragoverevento se puede utilizar para indicar destinos de colocación válidos, donde se puede colocar el elemento arrastrado.

La configuración para permitir que se coloque también requiere el bloqueo  dragenter y  dragover el manejo predeterminado de eventos.

<div ondragenter="event.preventDefault()">
复制代码

Haz un ejemplo para entender 可放置目标:

objeto de transferencia de datos

DataTransfer El objeto se utiliza para guardar los datos durante el proceso de arrastre, establecer el tipo de arrastre, etc.  El objeto se puede obtener en las propiedades eventde  todos los eventos de arrastre  .dataTransferDataTransfer

  • dataTransfer.dropEffect设置拖拽的操作类型。值必须是nonecopylink 或 move
function dragover(e) {
    e.preventDefault()
    e.dataTransfer.dropEffect = 'move'
}
复制代码
  • 传递数据 (不建议使用这种方法,可能有兼容问题)只能在drop事件中接收(测试的时候在其他拖拽事件中获取不到)
function dragstart(e, index) {
	e.stopPropagation()
	e.dataTransfer.dropEffect = 'move'
        // 传数据
	e.dataTransfer.setData('text/plain', '111111111')
}
function drop(e) {
        // 接收数据
	console.log(e.dataTransfer.getData('text/plain'));
}
复制代码

Vue3 中拖拽排序

根据上面描述的属性和事件在 Vue3 编写一个拖拽排序的列表大概分下面几个步骤:

  1. 创建一个列表,遍历渲染到页面
  2. 列表项添加 draggable="true"
  3. 列表项添加事件 dragstart dragenter dragend dragover
  4. dragenter 事件中,需要传入列表项的下标,实时进行元素的排序。排序的核心逻辑也是在 dragenter
  5. 代码执行的逻辑是:列表项拖拽到可放置目标时,将该拖拽的元素从原位置删除,再将拖拽的元素插入到当前可放置目标的位置

代码如下:

<template>
    <div>
            <div
                class="item"
                v-for="(item, i) in drag.list"
                :key="item.id"
                draggable="true"
                @dragstart="dragstart($event, i)"
                @dragenter="dragenter($event, i)"
                @dragend="dragend"
                @dragover="dragover"
               >
                {{ item.name }}
            </div>
    </div>
</template>
<script setup>
import { reactive } from 'vue'
const drag = reactive({
	list: [
		{ name: 'a', id: 1 },
		{ name: 'b', id: 2 },
		{ name: 'c', id: 3 },
		{ name: 'd', id: 4 },
		{ name: 'e', id: 5 },
	]
})

let dragIndex = 0

function dragstart(e, index) {
	e.stopPropagation()
	dragIndex = index
	setTimeout(() => {
		e.target.classList.add('moveing')
	},0)
}
function dragenter(e, index) {
	e.preventDefault()
	// 拖拽到原位置时不触发
	if (dragIndex !== index) {
		const source = drag.list[dragIndex];
		drag.list.splice(dragIndex, 1);
		drag.list.splice(index, 0, source);

		// 更新节点位置
		dragIndex = index
	}
}
function dragover(e) {
	e.preventDefault()
	e.dataTransfer.dropEffect = 'move'
}
function dragend(e) {
	e.target.classList.remove('moveing')
}
</script>

<style lang="scss" scoped>
.item {
	width: 200px;
	height: 40px;
	line-height: 40px;
	// background-color: #f5f6f8;
	background-color: skyblue;
	text-align: center;
	margin: 10px;
	color: #fff;
	font-size: 18px;
}

.container {
  position: relative;
  padding: 0;
}

.moveing {
	opacity: 0;
}
</style>
复制代码

此时是这样的效果:

动画.gif

这样就在 Vue3 中实现了拖拽排序。还可以利用 Vue 的<TransitionGroup> 内置组件,添加动画效果,让元素的过渡不会很生硬。

添加代码:

<template>
<div>
	<TransitionGroup name="list" tag="div" class="container">
		<div
			class="item"
			v-for="(item, i) in drag.list"
			:key="item.id"
			draggable="true"
			@dragstart="dragstart($event, i)"
			@dragenter="dragenter($event, i)"
			@dragend="dragend"
			@dragover="dragover"
		>
			{{ item.name }}
		</div>
	</TransitionGroup>
</div>
</template>

<style lang="scss" scoped>
    .list-move, /* 对移动中的元素应用的过渡 */
    .list-enter-active,
    .list-leave-active {
        transition: all 0.2s ease;
    }
</style>
复制代码

效果如下:

222.gif

sortable.js

接下来在 Element Plus 组件库中使用 sortable.js 进行表格排序。

Element Plus 是基于 Vue3 的常用的开源组件库

安装 sortable.js

npm i sortablejs -S
复制代码

使用 el-table 组件,写一个表格:

<template>
<div>
        <el-table :data="tableData" id="dragTable" border style="width: 800px;">
                <el-table-column prop="date" label="Date" width="180" />
                <el-table-column prop="name" label="Name" width="180" />
                <el-table-column prop="address" label="Address" />
        </el-table>
</div>
</template>

<script setup>
const tableData = [
	{
		date: '2016-05-03',
		name: 'Tom',
		address: 'No. 189, Grove St, Los Angeles',
	},
	{
		date: '2016-05-02',
		name: 'Cilly',
		address: 'No. 189, Grove St, Los Angeles',
	},
	{
		date: '2016-05-04',
		name: 'Linda',
		address: 'No. 189, Grove St, Los Angeles',
	},
	{
		date: '2016-05-01',
		name: 'John',
		address: 'No. 189, Grove St, Los Angeles',
	},
]
</script>
复制代码

现在就有了一个表格:

捕获.PNG

然后导入 sortable.js

<script setup>
import Sortable from 'sortablejs'
import { onMounted } from 'vue'

function setSort() {
    const el = document.querySelector('#dragTable table tbody')
    new Sortable(el, {
    sort: true,
		ghostClass: 'sortable-ghost',
		onEnd: (e) => {
			const targetRow = tableData.splice(e.oldIndex, 1)[0]
			tableData.splice(e.newIndex, 0, targetRow)
			console.log(tableData)
		},
	})
}
onMounted(() => {
	setSort()
})

const tableData = [
 // ...
]
</script>
复制代码

onMounted 中,也就是组件挂载完成之后,实例化 Sortable(),传入要进行拖拽排序的节点 el 和其它一些配置参数。现在可以进行拖拽了。

333.gif

有些时候,可能需要按住拖动图标才可以进行拖动,需要添加 handle 配置,并指定对应的样式名。

    <el-table :data="tableData" id="dragTable" border style="width: 600px; margin: 20px">
      <!-- ...... 省略代码 -->
      <el-table-column label="操作" width="100">
        <template #default>
          <div class="handle-drag">
            <el-icon>
              <Sort />
            </el-icon>
          </div>
        </template>
      </el-table-column>
    </el-table>
复制代码

上面代码将表格添加了一个操作列,并将操作列的图标设置一个样式类。下面的配置表示只有包含.handle-drag 样式的元素才可以被拖动。其他位置不能被拖动。

  new Sortable(el, {
    // ...
    handle: '.handle-drag',
    // ...
  })
复制代码

444.gif

查看其他配置项

vuedraggable

vue.draggable.next 是 Vue3 的拖拽组件,是基于 Sortable.js 实现的。可以用于拖拽列表、菜单、工作台、选项卡等常见的场景。

安装:

npm i -S vuedraggable@next
复制代码

使用:

<script setup>
import draggable from 'vuedraggable'
import { reactive } from 'vue'

const state = reactive({
	list1: [1, 2, 3, 4],
	list2: ['a', 'b', 'c', 'd'],
})

function onStart() {}

function onEnd() {
	console.log(state)
}

</script>
复制代码

先导入 draggable并定义一些基础数据。

<template>
	<div style="margin-left: 30px;">
		<draggable
			:list="state.list1"
			:force-fallback="true"
			chosen-class="chosen"
			animation="300"
			@start="onStart"
			@end="onEnd"
		>
			<template #item="{ element }">
				<div class="item">
					{{ element }}
				</div>
			</template>
		</draggable>
	</div>
</template>
复制代码

其中 @start@end 为拖拽开始和结束时的事件。chosen-class 为拖拽时的样式。

555.gif

为组件设置相同的 group 属性,可以实现在不同的块之间拖拽。

		<draggable group="group" :list="state.list1" >
			<template #item="{ element }">
				<div class="item bck1">
					{{ element }}
				</div>
			</template>
		</draggable>

		<draggable group="group" :list="state.list2" >
			<template #item="{ element }">
				<div class="item bck2">
					{{ element }}
				</div>
			</template>
		</draggable>
复制代码

666.gif

相关地址

Supongo que te gusta

Origin juejin.im/post/7231519213897875512
Recomendado
Clasificación