Sortable.js功能強大的JavaScript 拖拽庫示例詳解
一、介紹
Sortable.js一個功能強大的JavaScript 拖拽庫?。。∮糜谠诰W(wǎng)頁上創(chuàng)建可拖放和可排序的元素。它提供了簡單而強大的 API,使開發(fā)人員能夠輕松地實現(xiàn)拖放功能,并允許用戶通過拖放來重新排序列表、網(wǎng)格和其他元素。
主要有以下特性:
- 兼容性好:支持觸屏設(shè)備和大部分瀏覽器,支持現(xiàn)代瀏覽器,并提供了對舊版瀏覽器的向后兼容性;
- 簡單:簡單的API,方便使用,通過簡單的HTML 結(jié)構(gòu)和 JavaScript API,可以快速實現(xiàn)拖放排序功能;
- 原生:基于原生HTML5中的拖放API;
- CSS框架兼容性:支持所有的css框架,像Bootstrap;
- 零依賴:不依賴Jquery等其他框架;
- SPA支持良好:支持多種框架(angular、vue、react等);
- 高度可定制:通過配置選項和回調(diào)函數(shù),可以自定義拖放行為和排序效果;
- 交互性:除了基本的拖放功能外,SortableJS 還提供了豐富的交互性選項,如拖放動畫、排序同步等; 社區(qū)支持:
- SortableJS有一個活躍的開發(fā)者社區(qū),為使用該庫的開發(fā)者提供支持、插件和示例。
二、安裝
1、npm安裝
npm install sortablejs --save
2、bower安裝
bower install --save sortablejs
3、script引入
<script src="../../js/Sortable.min.js"></script>
三、配置項
const sortable = new Sortable(el, {
// or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] }
group: "name",
// boolean 定義是否列表單元是否可以在列表容器內(nèi)進行拖拽排序
sort: true,
// number 定義鼠標(biāo)選中列表單元可以開始拖動的延遲時間;
delay: 0,
// px,在取消延遲拖動事件之前,點應(yīng)該移動多少像素
touchStartThreshold: 0,
// boolean 定義是否此sortable對象是否可用,為true時sortable對象不能拖放排序等功能,為false時為可以進行排序,相當(dāng)于一個開關(guān);
disabled: false,
// @see Store
store: null,
// ms, number 單位:ms,定義排序動畫的時間
animation: 150,
// 制作動畫。默認(rèn)為null,https://easings.net/。
easing: "cubic-bezier(1, 0, 0, 1)",
// 格式為簡單css選擇器的字符串,使列表單元中符合選擇器的元素成為拖動的手柄,只有按住拖動手柄才能使列表單元進行拖動
handle: ".my-handle",
// 過濾器,不需要進行拖動的元素
filter: ".ignore-elements",
// 在觸發(fā)過濾器`filter`的時候調(diào)用`event.preventDefault()`
preventOnFilter: true,
// 允許拖拽的項目類名
draggable: ".item",
// drop placeholder的css類名
ghostClass: "sortable-ghost",
// 被選中項的css 類名
chosenClass: "sortable-chosen",
// 正在被拖拽中的css類名
dragClass: "sortable-drag",
dataIdAttr: 'data-id',
// 交換區(qū)的閾值
swapThreshold: 1,
// 如果設(shè)置為 true,將始終使用反向交換區(qū)
invertSwap: false,
// 反向交換閾值,默認(rèn)情況下將設(shè)置為swapThreshold 值
invertedSwapThreshold: 1,
// 拖拽方向 (默認(rèn)情況下會自動判斷方向)
direction: 'horizontal',
// 忽略 HTML5拖拽行為,強制回調(diào)進行
forceFallback: false,
// 當(dāng)使用forceFallback的時候,被復(fù)制的dom的css類名
fallbackClass: "sortable-fallback",
// 將cloned DOM 元素掛到body元素上。
fallbackOnBody: false,
// 以像素為單位指定鼠標(biāo)在被視為拖動之前應(yīng)移動的距離。
fallbackTolerance: 0,
// 是否啟用滾動,值為true或者HTMLElement
scroll: true,
// 自定義滾動
scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... },
// 鼠標(biāo)必須離邊緣多近才能開始滾動,單位 px
scrollSensitivity: 30,
// 滾動速度,px
scrollSpeed: 10,
// 將自動滾動應(yīng)用于所有父元素,以便更輕松地移動
bubbleScroll: true,
dragoverBubble: false,
// 刪除不顯示的克隆元素,而不是僅僅隱藏它
removeCloneOnHide: true,
// 拖動時鼠標(biāo)必須與空可排序項的距離(以像素為單位),以便將拖動元素插入到該可排序項中, 設(shè)置為0禁用此功能。
emptyInsertThreshold: 5,
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
},
// 結(jié)束拖拽
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
},
// 列表內(nèi)元素順序更新的時候觸發(fā)
onUpdate: function (/**Event*/evt) {
// same properties as onEnd
},
// 列表的任何更改都會觸發(fā)
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一個元素的時候觸發(fā)
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
}
}); 1.屬性
(1)group:string or object
- string:命名,個人建議用元素id就行,用處是為了設(shè)置可以拖放容器時使用,在array中的put的設(shè)置中再做介紹。
- object:{name,pull,put}。
name:同string的方法。
pull:pull用來定義從這個列表容器移動出去的設(shè)置,true/false/‘clone’/function。true:列表容器內(nèi)的列表單元可以被移出;false:列表容器內(nèi)的列表單元不可以被移出;‘clone’:列表單元移出,移動的為該元素的副本;function:用來進行pull的函數(shù)判斷,可以進行復(fù)雜邏輯,在函數(shù)中return false/true來判斷是否移出。
put:put用來定義往這個列表容器放置列表單元的的設(shè)置,true/false/[‘foo’,‘bar’]/function。true:列表容器可以從其他列表容器內(nèi)放入列表單元;false:與true相反; [‘foo’,‘bar’]:這個可以是一個字符串或者是字符串的數(shù)組,代表的是group配置項里定義的name值; function:用來進行put的函數(shù)判斷,可以進行復(fù)雜邏輯,在函數(shù)中return false/true來判斷是否放入。
(2)sort:boolean 定義是否列表單元是否可以在列表容器內(nèi)進行拖拽排序;
(3)delay:number 定義鼠標(biāo)選中列表單元可以開始拖動的延遲時間;
(4)disabled:boolean 定義是否此sortable對象是否可用,為true時sortable對象不能拖放排序等功能,為false時為可以進行排序,相當(dāng)于一個開關(guān);
(5)animation:number 單位:ms,定義排序動畫的時間;
(6)handle:selector 格式為簡單css選擇器的字符串,使列表單元中符合選擇器的元素成為拖動的手柄,只有按住拖動手柄才能使列表單元進行拖動;
**(7)filter:**selector 格式為簡單css選擇器的字符串,定義哪些列表單元不能進行拖放,可設(shè)置為多個選擇器,中間用“,”分隔;
(8)draggable:selector 格式為簡單css選擇器的字符串,定義哪些列表單元可以進行拖放
(9)ghostClass:selector 格式為簡單css選擇器的字符串,當(dāng)拖動列表單元時會生成一個副本作為影子單元來模擬被拖動單元排序的情況,此配置項就是來給這個影子單元添加一個class,我們可以通過這種方式來給影子元素進行編輯樣式;
(10)chosenClass:selector 格式為簡單css選擇器的字符串,當(dāng)選中列表單元時會給該單元增加一個class;
(11)forceFallback:boolean 如果設(shè)置為true時,將不使用原生的html5的拖放,可以修改一些拖放中元素的樣式等;
(12)fallbackClass:string 當(dāng)forceFallback設(shè)置為true時,拖放過程中鼠標(biāo)附著單元的樣式;
(13)scroll:boolean 默認(rèn)為true,當(dāng)排序的容器是個可滾動的區(qū)域,拖放可以引起區(qū)域滾動。
2.事件
onChoose:function 列表單元被選中的回調(diào)函數(shù)
onStart:function 列表單元拖動開始的回調(diào)函數(shù)
onEnd:function 列表單元拖放結(jié)束后的回調(diào)函數(shù)
onAdd:function 列表單元添加到本列表容器的回調(diào)函數(shù)
onUpdate:function 列表單元在列表容器中的排序發(fā)生變化后的回調(diào)函數(shù)
onRemove:function 列表元素移到另一個列表容器的回調(diào)函數(shù)
onFilter:function 試圖選中一個被filter過濾的列表單元的回調(diào)函數(shù)
onMove:function 當(dāng)移動列表單元在一個列表容器中或者多個列表容器中的回調(diào)函數(shù)
onClone:function 當(dāng)創(chuàng)建一個列表單元副本的時候的回調(diào)函數(shù)
3.事件對象
事件對象在各個函數(shù)中略有不同,可通過輸出對象查看對象的屬性,下面簡單列舉幾個:
to:HTMLElement–移動到列表容器
from:HTMLElement–來源的列表容器
item:HTMLElement–被移動的列表單元
clone:HTMLElement–副本的列表單元
oldIndex:number/undefined–在列表容器中的原序號
newIndex:number/undefined–在列表容器中的新序號
4.方法
option(name[,value])
獲得或者設(shè)置項參數(shù),使用方法類似于jQuery用法,沒有第二個參數(shù)為獲得option中第一個參數(shù)所對應(yīng)的值,有第二個參數(shù)時,將重新賦給第一個參數(shù)所對應(yīng)的值;
closest
沒理解
toArray()
序列化可排序的列表單元的data-id(可通過配置項中dataIdAttr修改)放入一個數(shù)組,并返回這個數(shù)組中
sort()
通過自定義列表單元的data-id的數(shù)組對列表單元進行排序
save()
destroy()
四、實戰(zhàn)應(yīng)用
1.Vue先把數(shù)據(jù)渲染到頁面上;
2.利用sortablejs操作真實dom,得到列表,sortablejs 核心就是操作真實dom,這時候由于vue本身數(shù)據(jù)未更新,所以也不會觸發(fā)dom的重新渲染,這就導(dǎo)致了vue里面的數(shù)據(jù)與真實dom的數(shù)據(jù)是對不上的,所以有了第3步;
3.利用sortablejs的onEnd方法把數(shù)據(jù)變化映射到真實的vue的數(shù)據(jù)源list上,實現(xiàn)拖拽時dom變化是對應(yīng)的。
環(huán)境如下:

1、簡單列表拖拽
<script setup lang="ts">
import Sortable from 'sortablejs'
import { ref, onMounted, nextTick } from 'vue';
const sortableRef = ref(null)
const list = [
{
name: 'item1'
},
{
name: 'item2'
},
{
name: 'item3'
},
{
name: 'item4'
},
{
name: 'item5'
},
{
name: 'item6'
}
]
const initSortable = () => {
new Sortable(sortableRef.value, {
delay: 10,
animation: 150,
// 如果有不想排序的,在這里按照class匹配的方式寫出即可
filter: '.demo-title',
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
draggable: '.demo-item',
// drop placeholder的css類名
ghostClass: 'blue-background-class'
});
}
onMounted(() => {
nextTick(() => {
initSortable()
})
})
</script>
<template>
<ul ref="sortableRef" class="demo">
<li class="demo-title">Demo</li>
<li class="demo-item" v-for="item in list" :key="item.name">{{ item.name }}</li>
</ul>
</template>
<style lang="scss" scoped>
.demo {
list-style: none;
width: 40%;
margin: 200px auto 0;
.demo-title {
text-align: center;
font-weight: 600;
font-size: 16px;
}
.demo-item {
border: 1px solid red;
margin: 10px 0;
padding: 10px 0;
text-align: center;
}
}
.blue-background-class {
background-color: #1890ff;
}
</style>效果如下:

2、多列表相互拖拽
<script setup lang="ts">
import Sortable from 'sortablejs'
import { ref, onMounted, nextTick } from 'vue';
const demo1Ref = ref(null)
const demo2Ref = ref(null)
const initSortable = () => {
new Sortable(demo1Ref.value, {
// 相互拖拽列表的組名必須一樣
group: 'shared',
delay: 10,
animation: 150,
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
// 拖拽元素的類名一樣,否則其它列表拖過來的不能在當(dāng)前列表拖動
draggable: '.demo-item'
});
new Sortable(demo2Ref.value, {
// 相互拖拽列表的組名必須一樣
group: 'shared',
delay: 10,
animation: 150,
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
// 拖拽元素的類名一樣,否則其它列表拖過來的不能在當(dāng)前列表拖動
draggable: '.demo-item'
});
}
onMounted(() => {
nextTick(() => {
initSortable()
})
})
</script>
<template>
<div class="demo-container">
<ul ref="demo1Ref" class="demo">
<li class="demo-item demo1-item" v-for="item in 6" :key="'demo1'+item">item{{ item }}</li>
</ul>
<ul ref="demo2Ref" class="demo">
<li class="demo-item demo2-item" v-for="item in 6" :key="'demo2'+item">item{{ item }}</li>
</ul>
</div>
</template>
<style lang="scss" scoped>
.demo-container {
display: flex;
justify-content: space-between;
width: 1000px;
.demo {
list-style: none;
width: 48%;
.demo-item {
margin: 10px 0;
padding: 10px 0;
text-align: center;
}
.demo1-item {
background-color: #5ac8fa;
}
.demo2-item {
background-color: #c0ca33;
}
}
}
</style> 效果如下:

3、克隆(通過拖拽復(fù)制節(jié)點)
new Sortable(demo1Ref.value, {
group: {
name: 'shared',
pull: 'clone' // To clone: set pull to 'clone'
},
delay: 10,
animation: 150,
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
// 拖拽元素的類名一樣,否則其它列表拖過來的不能在當(dāng)前列表拖動
draggable: '.demo-item'
});
new Sortable(demo2Ref.value, {
group: {
name: 'shared',
pull: 'clone' // To clone: set pull to 'clone'
},
delay: 10,
animation: 150,
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
// 拖拽元素的類名一樣,否則其它列表拖過來的不能在當(dāng)前列表拖動
draggable: '.demo-item'
});效果如下:

4、禁止sorting
坐標(biāo)的列表無法進行排序,因為設(shè)置了禁止sort,但是你還是可以從左邊拖拽到右邊。
new Sortable(demo1Ref.value, {
group: {
name: 'shared',
pull: 'clone',
put: false // 不允許拖拽進這個列表
},
sort: false, // 設(shè)為false,禁止sort
delay: 10,
animation: 150,
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
// 拖拽元素的類名一樣,否則其它列表拖過來的不能在當(dāng)前列表拖動
draggable: '.demo-item'
});
new Sortable(demo2Ref.value, {
group: 'shared',
delay: 10,
animation: 150,
// 需要拖拽的標(biāo)簽的class,強烈推薦寫
// 拖拽元素的類名一樣,否則其它列表拖過來的不能在當(dāng)前列表拖動
draggable: '.demo-item'
});效果如下:

5、Handle
使列表單元中符合選擇器的元素成為拖動的手柄,只有按住拖動手柄才能使列表單元進行拖動。在面代碼中只有按住白色方塊才能拖動元素。
<script setup lang="ts">
import Sortable from 'sortablejs'
import { ref, onMounted, nextTick } from 'vue';
const sortableRef = ref(null)
const initSortable = () => {
new Sortable(sortableRef.value, {
handle: '.handle-draggabel',
animation: 150,
});
}
onMounted(() => {
nextTick(() => {
initSortable()
})
})
</script>
<template>
<ul ref="sortableRef" class="demo">
<li class="demo-item" v-for="item in 6" :key="item">
<span class="handle-draggabel"></span>
<span>item{{ item }}</span>
</li>
</ul>
</template>
<style lang="scss" scoped>
.demo {
list-style: none;
width: 40%;
.demo-item {
background-color: #1890ff;
margin: 10px 0;
padding: 10px 0;
color: #fff;
text-align: center;
.handle-draggabel {
display: inline-block;
width: 14px;
height: 14px;
background-color: #fff;
margin-right: 10px;
cursor: pointer;
}
}
}
</style>效果如下:

五、總結(jié)
除了基本的拖放功能外,SortableJS 還提供了許多額外的功能和選項,例如拖放動畫、排序同步、多選模式等。這些功能可以幫助您創(chuàng)建更加豐富和用戶友好的交互體驗。
SortableJS 的社區(qū)非?;钴S,許多開發(fā)者使用該庫并為其貢獻插件和示例。這意味著您可以找到許多現(xiàn)成的解決方案和資源,以幫助您解決在開發(fā)中遇到的問題。
總的來說,SortableJS 是一個強大、靈活且易于使用的 JavaScript 庫,適用于各種類型的拖放排序需求。無論是簡單的列表排序還是復(fù)雜的交互式應(yīng)用程序,SortableJS 都能夠幫助您快速實現(xiàn)所需的功能。如果您正在尋找一個可靠的拖放庫來增強您的網(wǎng)頁或應(yīng)用程序的交互性,SortableJS 是一個值得考慮的選擇。
文檔地址:http://www.sortablejs.com/index.html
到此這篇關(guān)于Sortable.js功能強大的JavaScript 拖拽庫示例詳解的文章就介紹到這了,更多相關(guān)Sortable.js JavaScript 拖拽庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
了解在JavaScript中將值轉(zhuǎn)換為字符串的5種方法
這篇文章主要介紹了在JavaScript中將值轉(zhuǎn)換為字符串的5種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,下面小編就和大家一起來學(xué)習(xí)下吧2019-06-06
Makefile/cmake/node-gyp中區(qū)分判斷不同平臺的方法
今天小編就為大家分享一篇關(guān)于Makefile/cmake/node-gyp中區(qū)分判斷不同平臺的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
如何根據(jù)百度地圖計算出兩地之間的駕駛距離(兩種語言js和C#)
本文給大家介紹分別使用js和c#兩種語言實現(xiàn)根據(jù)百度地圖計算出兩地之間的駕駛距離,需要用戶指定出發(fā)城市和到達城市。對百度地圖計算兩地距離感興趣的朋友可以參考下本篇文章2015-10-10

