v-model
Compatible – 依照v-model
标准让所有数组可编辑- Mixin Components – 使用
Mixin
与你现有的组件集成 - Standalone Components – 对于简单的列表直接使用现成组件
- Drag handle, auto-scrolling, locked axis, events, and more! - 拖拽 handle,自动滚动,坐标轴锁定,事件等等
- Suuuper smooth animations – 追逐 60FPS 的梦想 🌈
- Horizontal lists, vertical lists, or a grid ↔ ↕ ⤡ - 支持水平列表,垂直列表和网格
- Touch support 👌- 支持触控操作
- Oh yeah, and it's DEPENDENCY FREE! 👌- 没有依赖其他库
使用 npm:
$ npm install vue-slicksort --save
使用 yarn:
$ yarn add vue-slicksort
使用 CDN:
<script src="https://unpkg.com/vue-slicksort@latest/dist/vue-slicksort.min.js"></script>
然后,使用支持 CommonJS 或者 ES2015 modules 的模块打包工具,例如 webpack:
// 使用类似 Babel 这样的 ES6 编译工具
import { ContainerMixin, ElementMixin } from 'vue-slicksort';
// 不使用 ES6 的编译工具
var slicksort = require('vue-slicksort');
var ContainerMixin = slicksort.ContainerMixin;
var ElementMixin = slicksort.ElementMixin;
如果你通过 <script>
标签加载:
<script>
var { ContainerMixin, ElementMixin, HandleDirective } = window.VueSlicksort;
</script>
import Vue from 'vue';
import { ContainerMixin, ElementMixin } from 'vue-slicksort';
const SortableList = {
mixins: [ContainerMixin],
template: `
<ul class="list">
<slot />
</ul>
`,
};
const SortableItem = {
mixins: [ElementMixin],
props: ['item'],
template: `
<li class="list-item">{{item}}</li>
`,
};
const ExampleVue = {
name: 'Example',
template: `
<div class="root">
<SortableList lockAxis="y" v-model="items">
<SortableItem v-for="(item, index) in items" :index="index" :key="index" :item="item"/>
</SortableList>
</div>
`,
components: {
SortableItem,
SortableList,
},
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7', 'Item 8'],
};
},
};
const app = new Vue({
el: '#root',
render: (h) => h(ExampleVue),
});
就这样!默认情况下,Vue Slickort 不附带任何样式,因为它的目的是在现有组件上做扩展。
为了实现两个 mixins 预先设置了两个组件,使用方式如下:
import { SlickList, SlickItem } from 'vue-slicksort';
const ExampleVue = {
name: 'Example',
template: `
<div class="root">
<SlickList lockAxis="y" v-model="items">
<SlickItem v-for="(item, index) in items" :index="index" :key="index">
{{ item }}
</SlickItem>
</SlickList>
</div>
`,
components: {
SlickItem,
SlickList,
},
data() {
return {
items: ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7', 'Item 8'],
};
},
};
现在已经有一些很好的(Drag & Drop)拖放库了(例如, vuedraggable 就很棒),如果这些库能满足你的需求,你应该先试一下他们。然而,大部分的库依赖 HTML5 的(Drag & Drop)拖放 API,会有一些严重的兼容或限制问题。例如,如果你需要支持触控设备,再如果你需要锁定只在一个坐标方向上拖动,或者想要在节点进行排序时有动画,这些都会变得很麻烦。Vue Slicksort 提供了一系列简单的组件混入旨在解决之前提到的这些问题。如果你正在寻找一种非常简单、移动友好的方式将可排序功能添加到你的列表中,那么你算是来对地方了。
你可以在任何使用了 ContainerMixin
的组件上应用单一的 props
选项,在执行排序期间,该组件还会发出几个事件。下面是一个自定义组件的示例
You apply options as individual props
on whatever component is using the ContainerMixin
. The component also emits several events during a sorting operation. Here's an example of a customized component:
<SortableContainer
:value="items"
:transitionDuration="250"
:lockAxis="'y'"
:useDragHandle="true"
@sort-start="onSortStart($event)"
>
<!-- SortableElement 的内容放在这里 -->
</SortableContainer>
type: Array
value
可以从v-model
继承,但必须设置为 Container
里面 v-for
遍历的列表相同的列表
type: String
default: y
条目能按照水平,垂直,或者网格进行拖动,可选值有: x
, y
or xy
type: String
当在排序时,你可以按照你的意愿锁定一个坐标轴方向进行移动,这是 HTML5 的 Drag & Drop 做不到的。可选值有: x
, y
or xy
type: String
如果你想给排序中的元素添加一些样式(注意:这个 class 是加给正在排序的那个拖起来的元素的),可以用这个属性。
type: String
default: body
如果你想给正在排序的元素指定一个父元素并添加进去,可以使用这个属性,提供一个字符串的 querySelector 即可,默认是添加到 body 中的。
type: Number
default: 300
被拖动的元素移动时,其他元素的过渡持续时间(即 transition 属性的 duration),如果你想把过渡动画取消,可以设置成 0 。
type: Number
default: null
覆写拖动的元素放开然后到安放位置的动画间隔时间(即放开拖拽后到元素进入安放位置的过渡时间),如果不设置,会按照 transitionDuration
的设置。
type: Number
default: 0
如果你希望元素仅在按下一定时间后才可排序,更改此属性即可。 移动端合理的值是 200
,此属性不能与 distance
一起使用。(这个属性可以用来解决拖动元素上有点击事件,但是点击事件不生效的情况)
type: Number
default: 5
忽略 press 事件之前可容忍的运动像素数
type: Number
default: 0
如果你希望元素仅在拖动一定的像素(即拖动一定距离)后才可排序,可以使用这个属性,此属性不能与 pressDelay
一起使用。(这个属性可以用来解决拖动元素上有点击事件,但是点击事件不生效的情况,个人感觉比 pressDelay 更合适)
type: Boolean
default: false
如果你使用的是 HandleDirective
,将其设置为 true
type: Boolean
default: false
如果需要,可以将 window
设置为滚动容器。(只有 Container
出现滚动条时才能看出效果)
type: Boolean
default: true
控制是否自动隐藏 ghost 元素。默认情况下,为方便起见,Vue Slicksort 列表将自动隐藏当前正在排序的元素。 如果你想应用自己的样式,请将其设置为 false 。
type: Boolean
default: false
你可以将可排序元素的移动锁定到其父容器 Container
。
type: OffsetValue
or [ OffsetValue
, OffsetValue
]*
default: "50%"
当 lockToContainerEdges
设置为 true
,这个属性可以控制可排序 helper(即拖起来的那个元素)与其父容器 Container
的顶部/底部边缘之间的偏移距离。百分比的值是相对于当前正在排序的项目的高度,如果希望为锁定容器的顶部和底部指定不同的行为,还可以传入一个 array
(例如:["0%","100%"]
)。
* OffsetValue
可以是有限 Number
,也可以是由数字和单位(px
or %
)组成的 String
。 例如: 10
(与 "10px"
相同), "50%"
type: Function
default: Function
该函数在排序开始之前被调用,可以用于编程方式在排序开始之前取消排序。 默认情况下,如果事件目标input
, textarea
, select
或 option
,它将取消排序。
type: Function
default: Function
可选的 function({node, index, collection})
返回 SortableHelper 的计算尺寸,有关更多详细信息,请参见默认实现。
事件是从 Container 元素发出的,可以使用 v-bind
或 @
指令绑定。
emits: { event: MouseEvent, node: HTMLElement, index: number, collection: string }
排序开始时触发。
emits: { event }
在排序期间移动鼠标时触发。
emits: { event, newIndex, oldIndex, collection }
排序结束时触发。
emits: Array
在排序结束然后新排序的列表生成后触发。
type: Number
这是元素在列表中的排序索引,是必填属性。
type: Number or String
default: 0
元素所属的集合。如果你在同一 Container
中有多组可排序元素,这将很有用。例子
type: Boolean
default: false
元素是否可排序
v-handle
指令在可拖动元素内部使用。(即用了这个指令,可以让拖动只在元素的某个位置生效)
Container
必须由 :useDragHandle
属性,且设置为 true
时才能正常工作。
这里有关于此的一个简单元素的例子
<template>
<li class="list-item">
<!-- 拖动只在 span 元素上生效 -->
<span v-handle class="handle"></span>
{{item.value}}
</li>
</template>
<script>
import { ElementMixin, HandleDirective } from 'vue-slicksort';
export default {
mixins: [ElementMixin],
directives: { handle: HandleDirective },
};
</script>
事件名已经全部从驼峰命名更改为中划线分隔(dash-case),以适应内联 HTML 模板。
需要排序一个网格中的元素?我们已经实现了,将 axis
属性设置成 xy
即可,当前仅限于支持所有格子设置相同宽度和高度的网格。我们会继续努力在不久的未来支持可变宽度的支持
在进行排序时,vue-slicksort
创建一个你正在排序的元素的克隆元素(即上面一直提到的 sortable-helper ),然后添加到 appendTo
属性设置的标签的末尾。原始的元素会一直在 DOM 中保持在原来的位置直到拖动结束(使用了内联样式使其不可见)。如果从 CSS 角度来看, sortable-helper 出了问题,可能是因为你的 draggable 元素的选择器依赖了一个不存在的父元素(还是刚才说的,因为 sortable-helper 位于 appendTo
属性设置的标签的末尾)。也可能是 z-index
的问题,例如,在一个 Bootstrap modal(弹框)中使用 vue-slicksort
,如果想让 sortable-helper 在弹框中展示出来,你就得增加它的 z-index
,来提高层级。
默认情况,vue-slicksort
在 mousedown
时立即出发。如果你想要阻止这种行为,有一些现成的方法。你可以在启用排序之前使用 distance
属性设置一个触发拖动的最小距离(单位是像素)。也可以在启用排序之前使用 pressDelay
增加一个触发拖动的延迟。或者你也可以使用HandleDirective
如果你在可排序列表中使用 scoped styles ,你可以使用 appendTo
属性。
Slicksort 无依赖。vue
是仅有的前置依赖。
这里有一个 vue-slicksort
的 demo 项目,可以 down 到本地跑起来,把上面介绍的属性和事件实际用一下。
如果你觉得发现了问题,请 报告该问题 以及所有相关详细信息以重现该问题。 提 issue 最简单的方法是 fork 此 jsfiddle 。
如果是个性化的支持请求,请用 question
标签标记 issue。
欢迎提交 Feature requests / pull requests 。
这个库很大程度上是基于 Claudéric Demers (@clauderic) 的 react-sortable-hoc ,它是一个表现非常好的简单且高效的拖拽库。