大家好,我是 simple ,我的理想是 利用科技手段来解决生活中遇到的各种问题

vuedraggable

vue-draggable 使用 Vue.js 的组件来实现拖放(拖动)效果。vue2和vue3在使用方面的区别不大,能区分的我都尽可能做了标注,所以就不分两篇文章了。

npm install vuedraggable --save # vue2
npm install vuedraggable@next --save # vue3
yarn add vuedraggable # vue2
yarn add vuedraggable@next # vue3

基本用法只需要在 Vue 项目中导入vuedraggable组件并注册即可:

import draggable from 'vuedraggable'
export default {
  components: {
    draggable

然后在模板中使用它:

<draggable v-model="list">
  <div v-for="element in list" class="list-element">{{element}}</div>
</draggable>
.list-element {
  padding: 10px;
  background: #eee;
data: {
  list: ['Item 1', 'Item 2', 'Item 3']

这将使这些列表项可拖拽排序。

<template>
  <div class="row">
    <div class="col-2">
      <div class="form-group">
          class="btn-group-vertical buttons"
          role="group"
          aria-label="Basic example"
          <button class="btn btn-secondary" @click="add">Add</button>
          <button class="btn btn-secondary" @click="replace">Replace</button>
        </div>
        <div class="form-check">
          <input
            id="disabled"
            type="checkbox"
            v-model="enabled"
            class="form-check-input"
          <label class="form-check-label" for="disabled">DnD enabled</label>
        </div>
      </div>
    </div>
    <div class="col-6">
      <h3>Draggable {{ draggingInfo }}</h3>
      <draggable
        :list="list"
        :disabled="!enabled"
        class="list-group"
        ghost-class="ghost"
        :move="checkMove"
        @start="dragging = true"
        @end="dragging = false"
          class="list-group-item"
          v-for="element in list"
          :key="element.name"
          {{ element.name }}
        </div>
      </draggable>
    </div>
    <rawDisplayer class="col-3" :value="list" title="List" />
  </div>
</template>
<script>
import draggable from "@/vuedraggable";
let id = 1;
export default {
  name: "simple",
  display: "Simple",
  order: 0,
  components: {
    draggable
  data() {
    return {
      enabled: true,
      list: [
        { name: "John", id: 0 },
        { name: "Joao", id: 1 },
        { name: "Jean", id: 2 }
      dragging: false
  computed: {
    draggingInfo() {
      return this.dragging ? "under drag" : "";
  methods: {
    add: function() {
      this.list.push({ name: "Juan " + id, id: id++ });
    replace: function() {
      this.list = [{ name: "Edgard", id: id++ }];
    checkMove: function(e) {
      window.console.log("Future index: " + e.draggedContext.futureIndex);
</script>
<style scoped>
.buttons {
  margin-top: 35px;
.ghost {
  opacity: 0.5;
  background: #c8ebfb;
</style>
<template>
  <div class="row">
    <div class="col-3">
      <h3>Draggable 1</h3>
      <draggable
        class="list-group"
        :list="list1"
        group="people"
        @change="log"
        itemKey="name"
        <template #item="{ element, index }">
          <div class="list-group-item">{{ element.name }} {{ index }}</div>
        </template>
      </draggable>
    </div>
    <div class="col-3">
      <h3>Draggable 2</h3>
      <draggable
        class="list-group"
        :list="list2"
        group="people"
        @change="log"
        itemKey="name"
        <template #item="{ element, index }">
          <div class="list-group-item">{{ element.name }} {{ index }}</div>
        </template>
      </draggable>
    </div>
    <rawDisplayer class="col-3" :value="list1" title="List 1" />
    <rawDisplayer class="col-3" :value="list2" title="List 2" />
  </div>
</template>
<script>
import draggable from "@/vuedraggable";
export default {
  name: "two-lists",
  display: "Two Lists",
  order: 1,
  components: {
    draggable
  data() {
    return {
      list1: [
        { name: "John", id: 1 },
        { name: "Joao", id: 2 },
        { name: "Jean", id: 3 },
        { name: "Gerard", id: 4 }
      list2: [
        { name: "Juan", id: 5 },
        { name: "Edgard", id: 6 },
        { name: "Johnson", id: 7 }
  methods: {
    add: function() {
      this.list.push({ name: "Juan" });
    replace: function() {
      this.list = [{ name: "Edgard" }];
    clone: function(el) {
      return {
        name: el.name + " cloned"
    log: function(evt) {
      window.console.log(evt);
</script>
<template>
  <div class="row">
    <div class="col-8">
      <h3>Draggable table</h3>
      <table class="table table-striped">
        <thead class="thead-dark">
            <th scope="col">Id</th>
            <th scope="col">Name</th>
            <th scope="col">Sport</th>
        </thead>
        <draggable v-model="list" tag="tbody" item-key="name">
          <template #item="{ element }">
              <td scope="row">{{ element.id }}</td>
              <td>{{ element.name }}</td>
              <td>{{ element.sport }}</td>
          </template>
        </draggable>
      </table>
    </div>
    <rawDisplayer class="col-3" :value="list" title="List" />
  </div>
</template>
<script>
import draggable from "@/vuedraggable";
export default {
  name: "table-example",
  display: "Table",
  order: 8,
  components: {
    draggable
  data() {
    return {
      list: [
        { id: 1, name: "Abby", sport: "basket" },
        { id: 2, name: "Brooke", sport: "foot" },
        { id: 3, name: "Courtenay", sport: "volley" },
        { id: 4, name: "David", sport: "rugby" }
      dragging: false
</script>
<style scoped>
.buttons {
  margin-top: 35px;
</style>

Props

value(vue2) 或 modelValue(vue3)

type:Array
require:false 
default:null 
输入要拖动的组件数组。通常与内部元素v-for指令引用的相同数组。

<draggable v-model="myArray">

type:Array 
require:false 
default:null
value属性的替代方案,list是一个与拖放同步的数组。 
主要区别是list属性使用splice方法更新数组,而value是不可变的。 
不要与value属性一起使用。

type:String
require:false 
default:'div'
draggable组件作为外部元素创建的HTML节点类型,用于包含的插槽。
也可以将Vue组件的名称作为元素传递。在这种情况下,draggable属性将传递给创建的组件。
如果需要为创建的组件设置props或事件,请参见下面的componentData。示例:

<draggable tag="ul">
  <li>...</li>
</draggable>

这将渲染:

<li>...</li>

而不是默认的div。也可以传入组件:

<draggable tag="todo-list">
  <todo-item v-for="item in list" :text="item.text" /> 
</draggable>

这将渲染todo-list组件,并将draggable prop传递给它。

clone

type:Function
require:false
default:(original) => { return original;}
当clone选项为true时,在源组件上调用以克隆元素的函数。唯一的参数是要克隆的viewModel元素,返回值是其克隆版本。
默认情况下,vue.draggable重用viewModel元素,所以如果要克隆或深度克隆它,必须使用这个钩子。示例:

clone: (original) => {
  let clone = JSON.parse(JSON.stringify(original))
  // 深度克隆并修改clone
  return clone 

这将在拖动操作期间深度克隆元素,而不是重新使用原始元素。你可以在这里执行任何自定义克隆逻辑。如果不提供clone prop,vue.draggable将简单地重新使用元素,而不是实际克隆它。所以,如果你的元素是Vue实例,或者您需要对其进行深度克隆,则必须提供clone prop。

type:Function
require:false
default:null
如果不为null,这个函数将以类似的方式调用Sortable onMove回调。返回false将取消拖动操作。

HTML:

<draggable :list="list" :move="checkMove">

javascript:

checkMove: function(evt){
    return (evt.draggedContext.element.name!=='apple');

componentData

type:Object
require:false
default:null
这个道具用于向通过声明的子组件传递额外信息。
• props: 要传递给子组件的道具
• attrs: 要传递给子组件的属性
• on: 要在子组件中订阅的事件

<draggable tag="el-collapse" :list="list" :component-data="getComponentData()">
    <el-collapse-item v-for="e in list" :title="e.title" :name="e.name" :key="e.name">
        <div>{{e.description}}</div>
     </el-collapse-item>
</draggable>  
methods: {
    handleChange() {
      console.log('changed');
    inputChanged(value) {
      this.activeNames = value;
    getComponentData() {
      return {
        on: {
          change: this.handleChange,
          input: this.inputChanged
        attrs:{
          wrap: true
        props: {
          value: this.activeNames

componentData prop允许您将props,attrs和on传递给tag prop声明的子组件。这使您可以完全控制子组件及其与父组件draggable的交互。

其他sortable参数

从vue.draggable的版本2.19开始,可以直接将Sortable选项设置为vue.draggable的props。

group: "name"// 可以简单理解为只要group相同,就可以互相拖拽     sort: true// 在列表内排序      delay: 0, // 定义排序应开始的时间(以毫秒为单位)     delayOnTouchOnly: false, // 只在用户使用触摸时延迟     touchStartThreshold: 0, // px,在取消延迟的拖动事件之前,点应移动的像素数      disabled: false// 如果设置为true,则禁用sortable。     store: null// @see Store      animation: 150// ms,移动项目时的动画速度排序,`0` - 无动画      easing: "cubic-bezier(1, 0, 0, 1)", // 动画缓动。默认为null。请参阅  示例。     handle: ".my-handle"// 列表项内的拖动句柄选择器      filter: ".ignore-elements"// 不导致拖动的选择器(字符串或函数)      preventOnFilter: true, // 触发时调用`filter` `event.preventDefault()`     draggable: ".item"// 指定元素内哪些项目应可拖动    dataIdAttr: 'data-id', // `toArray()` 方法使用的HTML属性    ghostClass: "sortable-ghost",  // 拖放占位符的类名      chosenClass: "sortable-chosen"// 选定项目的类名      dragClass: "sortable-drag"// 拖动项目的类名     swapThreshold: 1, // 交换区域的阈值      invertSwap: false, // 如果设置为true,则始终使用反转的交换区域      invertedSwapThreshold: 1, // 反转的交换区域的阈值(默认情况下将设置为swapThreshold值)      direction: 'horizontal', // Sortable的方向(如果未给定,则会自动检测)     forceFallback: false,  // 忽略HTML5 DnD行为,强制回退      fallbackClass: "sortable-fallback"// 使用forceFallback时克隆的DOM元素的类名      fallbackOnBody: false// 将克隆的DOM元素附加到文档正文      fallbackTolerance: 0, // 指定鼠标应移动的像素数,才被视为拖动。     dragoverBubble: false,      removeCloneOnHide: true, // 隐藏时删除克隆元素,而不仅仅是隐藏它      emptyInsertThreshold: 5, // px,鼠标离空sortable的距离,以将拖动元素插入其中

支持kebab-case属性。例如,ghost-class属性将转换为ghostClass Sortable选项。
设置handle,sortable和group选项的示例:

<draggable
        v-model="list"
        handle=".handle"  
        group="name"  
        ghost-class="ghost"  
        :sort="false"  
        @change="log"  
</draggable>

EVENT

• 支持Sortable事件:
• startaddremoveupdateendchooseunchoosesortfilterclone
• 在Sortable.js触发onStart, onAdd, onRemove, onUpdate, onEnd, onChoose, onUnchoose, onSort, onClone时,events将以相同的参数进行调用。

HTML:

<draggable :list="list" @end="onEnd">
  •  change事件 当list prop不为空并且相应的数组因拖放操作而改变时,将触发change事件。此事件将以一个参数调用,其中包含以下属性之一:
  •  added: 包含添加到数组中的元素的信息
  •  newIndex: 添加的元素的索引
  •  element: 添加的元素
  •  removed: 包含从数组中移除的元素的信息
  •  oldIndex: 移除之前元素的索引
  •  element: 被移除的元素
  •  moved: 包含在数组中移动的元素的信息
  •  newIndex: 移动的元素的当前索引
  •  oldIndex: 移动的元素的旧索引
  •  element: 移动的元素change 事件在list prop发生变化时触发,并提供有关添加,删除或移动元素的详细信息。这使您可以在数组因拖放操作而改变时执行自定义逻辑。
  • vue2限制:header或footer插槽无法与transition-group一起使用。

    Header 

    使用header插槽在vuedraggable组件内添加不可拖动元素。
    重要提示:它应与draggable选项一起使用来标记可拖动元素。请注意,header插槽将始终位于默认插槽之前,而不考虑其在模板中的位置。例如:

    <draggable v-model="myArray" draggable=".item"> 
        <div v-for="element in myArray" :key="element.id" class="item">
             {{element.name}} 
        </div>
        <button slot="header" @click="addPeople">Add</button>
    </draggable>
    

    Footer 

    使用footer插槽在vuedraggable组件内添加不可拖动元素。重要提示:它应与draggable选项一起使用来标记可拖动元素。请注意,footer插槽将始终位于默认插槽之后,而不考虑其在模板中的位置。例如:

    <draggable v-model="myArray" draggable=".item">  
        <div v-for="element in myArray" :key="element.id" class="item">  
             {{element.name}}  
        </div>
        <button slot="footer" @click="addPeople">Add</button>
    </draggable>
    

    从vue 2版本迁移:

  • 使用item插槽代替默认插槽来显示元素
  • 使用itemKey道具为项目提供键
  • <!-- vue 2 版本 -->
    <draggable v-model="myArray">  
       <div v-for="element in myArray" :key="element.id">{{element.name}}</div>
    </draggable>
    <!-- vue 3 版本 -->
    <draggable v-model="myArray" item-key="id">
      <template #item="{element}">
        <div>{{element.name}}</div>
       </template>
    </draggable>
    
  • 使用过渡时,现在应使用tag道具和componentData来创建过渡
  • <!-- vue 2 版本 -->
    <draggable v-model="myArray">
        <transition-group name="fade">
            <div v-for="element in myArray" :key="element.id">
                {{element.name}}
            </div>
        </transition-group>
    </draggable>
    <!-- vue 3 版本 -->
    <draggable v-model="myArray" tag="transition-group" :component-data="{name:'fade'}">
      <template #item="{element}">
        <div>{{element.name}}</div>
      </template>
    </draggable>
        simple_lau
            前端 @搬砖师傅
           
    粉丝