Clasificación de arrastrar y soltar de Vue

En el proyecto, encontré una clasificación de arrastrar y soltar que no se desarrolla a menudo. Después de usarla, la revisé yo mismo y resumí dos métodos de clasificación de arrastrar y soltar, que son adecuados para vue2 y vue3. Una es facilitar el arrastrar y soltar nativo arrastrable que viene con el elemento, y la otra es usar un complemento, que también es adecuado para dispositivos móviles.

1. Método de arrastre arrastrable nativo

// html 部分
<div v-for="item in list" class="account-item" :draggable="true" @dragstart="dragstart(item)"
     @dragenter="dragenter(item)" @dragend="dragend(item)">
     <p>{
    
    {
    
     item }}</p>
</div>

<script setup>
const list = ref(['1', '2', '3', '4', '5', '6'])
const clickVal = ref<string>();
const moveVal = ref<string>();
const endVal = ref<string>();

const dragstart = (item: string): void => {
    
    
  clickVal.value = item
}
const dragenter = (item: string): void => {
    
    
  moveVal.value = item
}
const dragend = (item: string): void => {
    
    
  endVal.value = item;
  let index = list.value.indexOf(item)     //移动元素的当前位置
  let moveObj = moveVal.value ? moveVal.value : ''
  let addIndex = list.value.indexOf(moveObj)     //要移动后的位置
  list.value.splice(index, 1)
  list.value.splice(addIndex, 0, item)
}
</script>

Dos, método de complemento sortablejs

Este complemento tiene funciones completas, puede arrastrar todo el dom, o puede mantener presionado un botón del elemento para arrastrar, y también es aplicable a la terminal móvil. página web oficial

instalar complemento

npm i sortablejs --save

Importar y usar

Para inicializar el complemento después de que se complete la representación de la estructura dom, cuando el mouse se mueve hacia el botón de clasificación, se indica "mantenga presionado y arrastre para ordenar".


Al hacerlo, también hice una revisión de los eventos de entrada y salida del mouse. Hay cinco eventos relacionados con el movimiento del ratón.
mousemove: se activa cuando el mouse se mueve dentro de un nodo. Este evento se dispara continuamente a medida que el mouse continúa moviéndose. Para evitar problemas de rendimiento, se recomienda hacer algunas restricciones en la función de escucha de este evento, por ejemplo, solo se puede ejecutar una vez dentro de un período de tiempo determinado.
mouseenter: activado cuando el mouse ingresa a un nodo, este evento no se activará cuando el mouse ingrese a un nodo secundario.
mouseover: se activa cuando el mouse ingresa a un nodo; ingresar un nodo secundario activará este evento nuevamente.
mouseout: se activa cuando el mouse abandona un nodo; dejar el nodo principal también activará este evento.
mouseleave: se activa cuando el mouse abandona un nodo; dejar el nodo principal no activará este evento.
Tanto el evento mouseover como el evento mouseenter se activan cuando el mouse ingresa a un nodo. La diferencia entre los dos es que el evento mouseenter solo se activa una vez, y siempre que el mouse se mueva dentro del nodo, el evento mouseover se activará varias veces en el nodo secundario.


<template>
	// v-if 会导致拿不到dom, 改成v-show可以解决
	<div v-if="list.length" ref="dragcon" id="dragcon">
		<div v-for="item in list" :key="item.id" class="account-item">
	     <p>{
    
    {
    
     item }}</p>
	     <div class="sort-btn relative cursor-default" @mouseenter="tipEnter(item.id)" @mouseleave="tipShow = false">
            <b>排序</b>
            <span v-show="(tipShow && Number(tipId) === Number(item.id))">长按拖动排序</span>
          </div>
		</div>
	</div>
	<div v-else>暂无数据</div>
</template>

<script lang="ts" setup>
import Sortable from "sortablejs"
const tipId = ref(0)
const tipEnter = (id) => {
    
    
  tipShow.value = true
  tipId.value = id
}
const initSortable = () => {
    
    
  const el = document.getElementById('dragcon')
  // 创建拖拽实例
  let dragTable = Sortable.create(el, {
    
    
    animation: 150,
    handle: ".sort-btn", // 触发拖动的按钮绑定类名sort-btn
    dragClass: "sort-active",
    chosenClass: "sort-active",
    dataIdAttr: 'id',
    // 结束拖动事件
    onEnd: ({
     
      newIndex, oldIndex }) => {
    
    
      console.log(newIndex, oldIndex)
      // 调后端接口。。。。。。
    },
  })
}
onMounted(async () => {
    
    
  nextTick(() => {
    
    
    initSortable()
  })
})
</script>

problemas encontrados

1. Si el arrastre no tiene éxito o el elemento arrastrado no es lo que esperaba, el navegador verifica el elemento para ver si la estructura fuera del elemento en bucle es incorrecta.
2. Además, no use el índice como el valor clave de la estructura del bucle v-for Después de ordenar, si ajusta la interfaz para consultar la lista, habrá problemas al renderizar.
3. Además, el no puede tomar la estructura de v-if en el div, y es posible que no pueda obtener la estructura dom. Soy perezoso. Es factible cambiar v-if a v-show. Espero otros métodos provistos por el jefe.

Elementos de configuración para el complemento sortablejs

var sortable = new Sortable(el, {
    
    
      group: "name",  // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }
       sort: true,  // boolean 定义是否列表单元是否可以在列表容器内进行拖拽排序
       delay: 0, // number 定义鼠标选中列表单元可以开始拖动的延迟时间;
       touchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag event
       disabled: false, // boolean 定义是否此sortable对象是否可用,为true时sortable对象不能拖放排序等功能,为false时为可以进行排序,相当于一个开关;
       store: null,  // @see Store
       animation: 150,  // ms, number 单位:ms,定义排序动画的时间
       easing: "cubic-bezier(1, 0, 0, 1)", // Easing for animation. Defaults to null. See https://easings.net/ for examples.
       handle: ".my-handle",  // 格式为简单css选择器的字符串,使列表单元中符合选择器的元素成为拖动的手柄,只有按住拖动手柄才能使列表单元进行拖动
       filter: ".ignore-elements",  // 过滤器,不需要进行拖动的元素
       preventOnFilter: true, //  在触发过滤器`filter`的时候调用`event.preventDefault()`
       draggable: ".item",  // 允许拖拽的项目类名
       ghostClass: "sortable-ghost",  // drop placeholder的css类名
       chosenClass: "sortable-chosen",  // 被选中项的css 类名
       dragClass: "sortable-drag",  // 正在被拖拽中的css类名
       dataIdAttr: 'data-id',
   
       swapThreshold: 1, // Threshold of the swap zone
       invertSwap: false, // Will always use inverted swap zone if set to true
       invertedSwapThreshold: 1, // Threshold of the inverted swap zone (will be set to swapThreshold value by default)
       direction: 'horizontal', // 拖拽方向 (默认情况下会自动判断方向)
   
       forceFallback: false,  // 忽略 HTML5拖拽行为,强制回调进行
   
       fallbackClass: "sortable-fallback",  // 当使用forceFallback的时候,被复制的dom的css类名
       fallbackOnBody: false,  // 将cloned DOM 元素挂到body元素上。
       fallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag.
   
       scroll: true, // or HTMLElement
       scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) {
    
     ... }, // if you have custom scrollbar scrollFn may be used for autoscrolling
       scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
       scrollSpeed: 10, // px
       bubbleScroll: true, // apply autoscroll to all parent elements, allowing for easier movement
   
       dragoverBubble: false,
       removeCloneOnHide: true, // Remove the clone element when it is not showing, rather than just hiding it
       emptyInsertThreshold: 5, // px, distance mouse must be from empty sortable to insert drag element into it
   
   
       setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
    
    
           dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent
       },
   
       // 元素被选中
       onChoose: function (/**Event*/evt) {
    
    
           evt.oldIndex;  // element index within parent
       },
   
       // 元素未被选中的时候(从选中到未选中)
       onUnchoose: function(/**Event*/evt) {
    
    
           // same properties as onEnd
       },
   
       // 开始拖拽的时候
       onStart: function (/**Event*/evt) {
    
    
           evt.oldIndex;  // element index within parent
       },
   
       // 结束拖拽
       onEnd: function (/**Event*/evt) {
    
    
           var itemEl = evt.item;  // dragged HTMLElement
           evt.to;    // target list
           evt.from;  // previous list
           evt.oldIndex;  // element's old index within old parent
           evt.newIndex;  // element's new index within new parent
           evt.clone // the clone element
           evt.pullMode;  // when item is in another sortable: `"clone"` if cloning, `true` if moving
       },
   
       // 元素从一个列表拖拽到另一个列表
       onAdd: function (/**Event*/evt) {
    
    
           // same properties as onEnd
       },
   
       // 列表内元素顺序更新的时候触发
       onUpdate: function (/**Event*/evt) {
    
    
           // same properties as onEnd
       },
   
       // 列表的任何更改都会触发
       onSort: function (/**Event*/evt) {
    
    
           // same properties as onEnd
       },
   
       // 元素从列表中移除进入另一个列表
       onRemove: function (/**Event*/evt) {
    
    
           // same properties as onEnd
       },
   
       // 试图拖拽一个filtered的元素
       onFilter: function (/**Event*/evt) {
    
    
           var itemEl = evt.item;  // HTMLElement receiving the `mousedown|tapstart` event.
       },
   
       // 拖拽移动的时候
       onMove: function (/**Event*/evt, /**Event*/originalEvent) {
    
    
           // Example: https://jsbin.com/nawahef/edit?js,output
           evt.dragged; // dragged HTMLElement
           evt.draggedRect; // DOMRect {left, top, right, bottom}
           evt.related; // HTMLElement on which have guided
           evt.relatedRect; // DOMRect
           evt.willInsertAfter; // Boolean that is true if Sortable will insert drag element after target by default
           originalEvent.clientY; // mouse position
           // return false; — for cancel
           // return -1; — insert before target
           // return 1; — insert after target
       },
   
       // clone一个元素的时候触发
       onClone: function (/**Event*/evt) {
    
    
           var origEl = evt.item;
           var cloneEl = evt.clone;
       },
   
       // 拖拽元素改变位置的时候
       onChange: function(/**Event*/evt) {
    
    
           evt.newIndex // most likely why this event is used is to get the dragging element's current index
           // same properties as onEnd
       }
   });

Supongo que te gusta

Origin blog.csdn.net/qq_38661597/article/details/131103384
Recomendado
Clasificación