v-drag

简介

v-drag 指令用于处理根据鼠标拖拽来变换目标元素形态、位置等的场景。

示例

拖动元素

在 GitHub 上编辑此页编辑
<template>
<article>
  <div
    ref="target"
    v-drag:target.translate
    class="target"
  />
</article>
</template>

<script>
import { drag } from 'veui'

export default {
  directives: {
    drag
  }
}
</script>

<style lang="less" scoped>
.target {
  width: 80px;
  height: 80px;
  background: #e7e7e7;
}
</style>

限制拖动范围

在 GitHub 上编辑此页编辑
<template>
<article>
  <div
    ref="container"
    class="container"
  >
    <div
      ref="target"
      v-drag:target.translate="{containment: 'container'}"
      class="target"
    />
  </div>
</article>
</template>

<script>
import { drag } from 'veui'

export default {
  directives: {
    drag
  }
}
</script>

<style lang="less" scoped>
.target {
  width: 80px;
  height: 80px;
  background: #e7e7e7;
}

.container {
  width: 100%;
  height: 300px;
  background: #f7f7f7;
}
</style>

拖动多个元素

主元素
在 GitHub 上编辑此页编辑
<template>
<article>
  <div
    ref="target1"
    v-drag:target1,target2,target3.translate
    class="target"
  >
    主元素
  </div>
  <div
    ref="target2"
    class="target"
  />
  <div
    ref="target3"
    class="target"
  />
</article>
</template>

<script>
import { drag } from 'veui'

export default {
  directives: {
    drag
  }
}
</script>

<style lang="less" scoped>
.target {
  width: 80px;
  height: 80px;
  background: #e7e7e7;
  display: inline-flex;
  margin-right: 40px;
  align-items: center;
  justify-content: center;
  vertical-align: top;
}

.container {
  width: 100%;
  height: 300px;
  background: #f7f7f7;
}
</style>

限制拖动方向

水平方向
垂直方向
在 GitHub 上编辑此页编辑
<template>
<article>
  <div
    ref="target1"
    v-drag:target1.translate.x
    class="target"
  >
    水平方向
  </div>
  <div
    ref="target2"
    v-drag:target2.translate.y
    class="target"
  >
    垂直方向
  </div>
</article>
</template>

<script>
import { drag } from 'veui'

export default {
  directives: {
    drag
  }
}
</script>

<style lang="less" scoped>
article {
  height: 200px;
}

.target {
  width: 80px;
  height: 80px;
  background: #e7e7e7;
  display: inline-flex;
  margin-right: 40px;
  align-items: center;
  justify-content: center;
  vertical-align: top;
}

.container {
  width: 100%;
  height: 300px;
  background: #f7f7f7;
}
</style>

水平排序

Lorem
ipsum
dolor
sit
amet
consectetur
adipiscing
elit
sed
do
eiusmod
tempor
incididunt
ut
labore
et
dolore
magna
aliqua

可以通过 v-drag.sortv-drag="{ type: 'sort', ... }" 来实现拖拽排序。

在 GitHub 上编辑此页编辑
<template>
<article>
  <transition-group
    ref="group"
    name="list"
    tag="div"
    class="items"
  >
    <div
      v-for="item in items"
      :key="item"
      v-drag.sort.x="{
        name: 'words',
        containment: 'group',
        sort: sortCallback,
      }"
      class="item"
    >
      {{ item }}
    </div>
  </transition-group>
</article>
</template>

<script>
import { drag } from 'veui'

const items = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'.split(/[,. ]+/).filter(Boolean)

export default {
  directives: {
    drag
  },
  data () {
    return {
      items
    }
  },
  methods: {
    sortCallback (fromIndex, toIndex) {
      let items = this.items
      let item = items[fromIndex]
      items.splice(fromIndex, 1)
      items.splice(toIndex, 0, item)
    }
  }
}
</script>

<style lang="less" scoped>
.items {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
}

.item {
  background: white;
  border: 1px solid pink;
  border-radius: 3px;
  margin: 0 10px 8px 0;
  padding: 1px 2px;
}

.list-move {
  transition: transform 200ms ease;
}
</style>

垂直排序

Lorem
ipsum
dolor
sit
amet
consectetur
adipiscing
elit
sed
do
eiusmod
tempor
incididunt
ut
labore
et
dolore
magna
aliqua
在 GitHub 上编辑此页编辑
<template>
<article>
  <transition-group
    ref="group"
    name="list"
    tag="div"
    class="items"
  >
    <div
      v-for="item in items"
      :key="item"
      v-drag.sort.y="{
        name: 'words',
        containment: 'group',
        sort: sortCallback,
      }"
      class="item"
    >
      {{ item }}
    </div>
  </transition-group>
</article>
</template>

<script>
import { drag } from 'veui'

const items = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'.split(/[,. ]+/).filter(Boolean)

export default {
  directives: {
    drag
  },
  data () {
    return {
      items
    }
  },
  methods: {
    sortCallback (fromIndex, toIndex) {
      let items = this.items
      let item = items[fromIndex]
      items.splice(fromIndex, 1)
      items.splice(toIndex, 0, item)
    }
  }
}
</script>

<style lang="less" scoped>
.item {
  background: white;
  border: 1px solid pink;
  border-radius: 3px;
  margin: 0 10px 8px 0;
  padding: 1px 2px;
}

.items {
  padding: 0;
  list-style-position: inside;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  height: 300px;
  resize: both;

  .item {
    width: 20%;
    border-color: peachpuff;
  }
}

.list-move {
  transition: transform 200ms ease;
}
</style>

API

绑定值

类型:Object

参数类型默认值描述
typestring-该参数指定拖动行为的类型,目前内置了 translate / sort 两种模式,可以进行扩展
disabledbooleanfalse该指令是否被禁用。
containmentstring | Vue | HTMLElement | Object-

目标元素在变换的时候,应当始终位于 containment 所指定的区域内。

如果通过 containment 解析出来是一个 DOM 元素,那么所有目标元素就应当在该元素内变换;如果解析出来是一个矩形区域描述(相对于视口的 top、left、width、height),那么所有目标元素就应当在该矩形区域内变换。

类型描述
string在指令所在组件上下文中,根据 ref 查找指定的 DOM 元素。传入 @window 则计算视口位置。
Vue根据组件实例找到 DOM 元素。
HTMLElement直接接收 DOM 元素。
Object

translate

接受任意包含 { top, left, width, height } 字段的普通对象,表示相对于视口的矩形区域的坐标和尺寸,四个字段均为 number 类型。

handlestring | Vue | HTMLElement-指定拖拽操作的“把手”元素,只有拖动对应元素才会触发拖拽。类型同 containment 参数(不支持普通 Object 类型)。
targetsArray<string | Vue | HTMLElement>[]

translate

该参数指定了目标元素集合,在指令所在元素上拖拽鼠标的时候,会按照指定的方式变换所有目标元素。

类型描述
string在指令所在组件上下文中,根据 ref 查找指定的 DOM 元素集合。
Vue组件实例,直接使用 vm.$el 元素。
HTMLElementDOM 元素,直接使用。
axisstring-限制所有目标元素只能在水平或者垂直方向上做变换或指定拖拽排序元素排列方向。可选值类型:'x' | 'y'
dragstartfunction(): Objectfunction() {}

鼠标拖拽开始事件的回调函数。回调参数为 ({ event: DragEvent })

dragfunction(): Objectfunction() {}

鼠标拖拽中事件的回调函数。回调参数为 ({ event, distanceX, distanceY })

参数类型描述
eventDragEvent原生拖拽事件对象。
distanceXnumber水平方向自拖拽开始以后移动的总距离。
distanceYnumber垂直方向自拖拽开始以后移动的总距离。
dragendfunction(): Objectfunction() {}鼠标拖拽结束事件的回调函数。回调参数同 drag
readyfunctionfunction() {}指令初始化完成的回调函数,会传出一个句柄对象参数,该对象上有一个 reset() 方法,用于将所有目标元素重置为变换之前的样子。
namestring-

sort

用来标记拖动排序分组名称,排序将在分组名称相同的元素间进行。

sortfunction(fromIndex: number, toIndex: number): void-

sort

排序指令仅仅通过该回调告诉用户排序的情况,即:从原来位置(fromIndex)移动到新位置(toIndex),需要自行据此对数据源进行更新。

修饰符

对应 Object 绑定值中的 type / axis 的值。例如:

<!-- 沿着垂直方向做位移变换 -->
<div v-drag.translate.y></div>

参数

对应 Object 绑定值中的 targets。值是一个用 , 分隔的、表示一到多个 ref 的字符串。例如:

<div v-drag:box1,box2></div>

扩展

可以通过继承 BaseHandler 扩展 v-drag 指令:

import BaseHandler from 'veui/directives/drag/BaseHandler'
import { registerHandler } from 'veui/directives/drag'

class RotateHandler extends BaseHandler { }

registerHandler('rotate', RotateHandler)

然后通过 type 参数使用 RotateHandler

<div v-drag="{ type: 'rotate' }"></div>
<!-- 或者 -->
<div v-drag.rotate></div>

BaseHandler

BaseHandler 中各成员的说明如下:

成员名类型描述
optionsObject解析出来的参数组成的对象。
contextVue指令所在的组件。
isDraggingboolean是否处于拖拽过程中。
startfunction(Object)绑定值中的 dragstart 字段。
dragfunction(Object)绑定值中的 drag 字段。
endfunction(Object)绑定值中的 dragend 字段。
destroyfunction()指令与 DOM 元素解绑的时候调用。
setOptionsfunction(options)设置参数。
resetfunction()重置变换。
在 GitHub 上编辑此页编辑