官网教程和demo Sortable.js
GitHub Sortable仓库
Sortable是基于原生js的拖拽库,没有多余的依赖,使用感十分友好,Sortable.min.js 大小约44KB,适合快速开发拖拽项目。
引入
CDN引入
<!-- jsDelivr :: Sortable :: Latest (https://www.jsdelivr.com/package/npm/sortablejs) -->
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
NPM引入方法见官网:GettingStarted
简单使用
<ul id="items"><li>item 1</li><li>item 2</li><li>item 3</li>
</ul>
<script>
var el = document.getElementById('items');
var sortable = Sortable.create(el);
</script>
//若需要附加属性,则调整上面create参数,例如
var sortable = Sortable.create(el, { animation: 150,ghostClass: 'blue-background-class',});
注:CDN引入后ghostClass似乎不生效
附加属性汇总
GitHub$Options
var sortable = new Sortable(el, {group: "name", // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }sort: true, // sorting inside listdelay: 0, // time in milliseconds to define when the sorting should startdelayOnTouchOnly: false, // only delay if user is using touchtouchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag eventdisabled: false, // Disables the sortable if set to true.store: null, // @see Storeanimation: 150, // ms, animation speed moving items when sorting, `0` — without animationeasing: "cubic-bezier(1, 0, 0, 1)", // Easing for animation. Defaults to null. See https://easings.net/ for examples.handle: ".my-handle", // Drag handle selector within list itemsfilter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function)preventOnFilter: true, // Call `event.preventDefault()` when triggered `filter`draggable: ".item", // Specifies which items inside the element should be draggabledataIdAttr: 'data-id', // HTML attribute that is used by the `toArray()` methodghostClass: "sortable-ghost", // Class name for the drop placeholderchosenClass: "sortable-chosen", // Class name for the chosen itemdragClass: "sortable-drag", // Class name for the dragging itemswapThreshold: 1, // Threshold of the swap zoneinvertSwap: false, // Will always use inverted swap zone if set to trueinvertedSwapThreshold: 1, // Threshold of the inverted swap zone (will be set to swapThreshold value by default)direction: 'horizontal', // Direction of Sortable (will be detected automatically if not given)forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick infallbackClass: "sortable-fallback", // Class name for the cloned DOM Element when using forceFallbackfallbackOnBody: false, // Appends the cloned DOM Element into the Document's BodyfallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag.dragoverBubble: false,removeCloneOnHide: true, // Remove the clone element when it is not showing, rather than just hiding itemptyInsertThreshold: 5, // px, distance mouse must be from empty sortable to insert drag element into itsetData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent},// Element is chosenonChoose: function (/**Event*/evt) {evt.oldIndex; // element index within parent},// Element is unchosenonUnchoose: function(/**Event*/evt) {// same properties as onEnd},// Element dragging startedonStart: function (/**Event*/evt) {evt.oldIndex; // element index within parent},// Element dragging endedonEnd: function (/**Event*/evt) {var itemEl = evt.item; // dragged HTMLElementevt.to; // target listevt.from; // previous listevt.oldIndex; // element's old index within old parentevt.newIndex; // element's new index within new parentevt.oldDraggableIndex; // element's old index within old parent, only counting draggable elementsevt.newDraggableIndex; // element's new index within new parent, only counting draggable elementsevt.clone // the clone elementevt.pullMode; // when item is in another sortable: `"clone"` if cloning, `true` if moving},// Element is dropped into the list from another listonAdd: function (/**Event*/evt) {// same properties as onEnd},// Changed sorting within listonUpdate: function (/**Event*/evt) {// same properties as onEnd},// Called by any change to the list (add / update / remove)onSort: function (/**Event*/evt) {// same properties as onEnd},// Element is removed from the list into another listonRemove: function (/**Event*/evt) {// same properties as onEnd},// Attempt to drag a filtered elementonFilter: function (/**Event*/evt) {var itemEl = evt.item; // HTMLElement receiving the `mousedown|tapstart` event.},// Event when you move an item in the list or between listsonMove: function (/**Event*/evt, /**Event*/originalEvent) {// Example: https://jsbin.com/nawahef/edit?js,outputevt.dragged; // dragged HTMLElementevt.draggedRect; // DOMRect {left, top, right, bottom}evt.related; // HTMLElement on which have guidedevt.relatedRect; // DOMRectevt.willInsertAfter; // Boolean that is true if Sortable will insert drag element after target by defaultoriginalEvent.clientY; // mouse position// return false; — for cancel// return -1; — insert before target// return 1; — insert after target// return true; — keep default insertion point based on the direction// return void; — keep default insertion point based on the direction},// Called when creating a clone of elementonClone: function (/**Event*/evt) {var origEl = evt.item;var cloneEl = evt.clone;},// Called when dragging element changes positiononChange: 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}
});