JS拖拽排序插件Sortable.js用法實(shí)例分析
本文實(shí)例講述了JS拖拽排序插件Sortable.js用法。分享給大家供大家參考,具體如下:
最近由于項(xiàng)目功能設(shè)計(jì)的原因,需要對(duì)table中的行實(shí)現(xiàn)拖拽排序功能,找來(lái)找去發(fā)現(xiàn)Sortable.js能很好的滿足這個(gè)需求,而且它還是開(kāi)源的,于是乎就開(kāi)始學(xué)習(xí)使用Sortable.js,再然后就有了這篇文章。
特點(diǎn):
- 輕量級(jí)但功能強(qiáng)大
- 移動(dòng)列表項(xiàng)時(shí)有動(dòng)畫(huà)
- 支持觸屏設(shè)備和大多數(shù)瀏覽器(IE9及以下除外)
- 支持單個(gè)列表容器內(nèi)部拖拽排序,也支持兩個(gè)列表容器互相拖拽排序
- 支持拖放操作和可選擇的文本
- 非常友善的滾動(dòng)效果
- 基于原生HTML5中的拖放API
- 支持多種框架(Angular、Vue、React等)
- 支持所有的CSS框架,如:Bootstrap
- 簡(jiǎn)單的API,方便調(diào)用
- CDN
- 不依賴于jQuery
下載地址:https://github.com/RubaXa/Sortable
或者點(diǎn)擊此處本站下載
運(yùn)行效果如下圖所示:

單個(gè)列表容器內(nèi)部拖拽排序
<head>
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Scripts/Sortable-master/Sortable.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var ul = document.getElementById("infos");
var sortable = new Sortable(ul, {
handle: "input,li",//設(shè)置li、input支持拖拽
animation: 150,//設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng)
// Element dragging started
onStart: function (/**Event*/evt) {
evt.oldIndex; // element index within parent,此處指的是li的索引值
},
// Element dragging ended
onEnd: function (/**Event*/evt) {
var lis = $("#infos li");
//拖拽完畢后重新設(shè)置序號(hào),使其連續(xù)
for (var i = 0; i < lis.length; i++) {
var no = $(lis[i]).find("input:eq(0)");
no.val(i + 1);
}
}
});
});
</script>
<style>
li{
cursor:pointer;
padding-bottom:5px;
list-style:none;
}
</style>
</head>
<body>
<ul id="infos">
<li>
<input type="text" value="1" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">objective</option>
<option value="2">proposition</option>
</select>
</li>
<li>
<input type="text" value="2" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">eliminate</option>
<option value="2">alige</option>
</select>
</li>
<li>
<input type="text" value="3" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">optimize</option>
<option value="2">deploy</option>
</select>
</li>
</ul>
</body>
兩個(gè)列表容器相互拖拽排序
<head>
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Scripts/Sortable-master/Sortable.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var infosOne = document.getElementById("infosOne");
var sortableOne = new Sortable(infosOne, {
group: "guo",//若需要在兩個(gè)列表容器間拖拽排序,那group的值必須相同
handle: "input,li",//設(shè)置li、input支持拖拽
animation: 150,//設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng)
// Element dragging started
onStart: function (/**Event*/evt) {
evt.oldIndex; // element index within parent,此處指的是li的索引值
},
// Element dragging ended
onEnd: function (/**Event*/evt) {
var lis = $("#infosOne li");
for (var i = 0; i < lis.length; i++) {
var no = $(lis[i]).find("input:eq(0)");
no.val(i + 1);
}
lis = $("#infosTwo li");
for (var i = 0; i < lis.length; i++) {
var no = $(lis[i]).find("input:eq(0)");
no.val(i + 1);
}
}
});
var infosTwo = document.getElementById("infosTwo");
var sortableTwo = new Sortable(infosTwo, {
group:"guo",//若需要在兩個(gè)列表容器間拖拽排序,那group的值必須相同
handle: "input,li",//設(shè)置li、input支持拖拽
animation: 150,//設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng)
// Element dragging started
onStart: function (/**Event*/evt) {
evt.oldIndex; // element index within parent,此處指的是li的索引值
},
// Element dragging ended
onEnd: function (/**Event*/evt) {
var lis = $("#infosOne li");
for (var i = 0; i < lis.length; i++) {
var no = $(lis[i]).find("input:eq(0)");
no.val(i + 1);
}
lis = $("#infosTwo li");
for (var i = 0; i < lis.length; i++) {
var no = $(lis[i]).find("input:eq(0)");
no.val(i + 1);
}
}
});
});
</script>
</head>
<body>
<ul id="infosOne">
<li>
<input type="text" value="1" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">objective</option>
<option value="2">proposition</option>
</select>
</li>
<li>
<input type="text" value="2" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">eliminate</option>
<option value="2">alige</option>
</select>
</li>
<li>
<input type="text" value="3" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">optimize</option>
<option value="2">deploy</option>
</select>
</li>
</ul>
<hr />
<ul id="infosTwo">
<li>
<input type="text" value="1" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">目標(biāo)任務(wù)</option>
<option value="2">論題議題</option>
</select>
</li>
<li>
<input type="text" value="2" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">消除排除</option>
<option value="2">機(jī)敏的敏捷的</option>
</select>
</li>
<li>
<input type="text" value="3" />
<input type="text" value="hierarchy" />
<select>
<option value="">--請(qǐng)選擇--</option>
<option value="1">優(yōu)化使最優(yōu)化</option>
<option value="2">發(fā)布部署</option>
</select>
</li>
</ul>
</body>
常見(jiàn)配置項(xiàng)及事件
var sortable = new Sortable(el, {
group: "name", // or { name: "...", pull: [true, false, clone], put: [true, false, array] }
sort: true, // sorting inside list
delay: 0, // time in milliseconds to define when the sorting should start
touchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag event
disabled: false, // Disables the sortable if set to true.
store: null, // @see Store
animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
handle: ".my-handle", // Drag handle selector within list items
filter: ".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 draggable
ghostClass: "sortable-ghost", // Class name for the drop placeholder
chosenClass: "sortable-chosen", // Class name for the chosen item
dragClass: "sortable-drag", // Class name for the dragging item
dataIdAttr: 'data-id',
forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in
fallbackClass: "sortable-fallback", // Class name for the cloned DOM Element when using forceFallback
fallbackOnBody: false, // Appends the cloned DOM Element into the Document's Body
fallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag.
scroll: true, // or HTMLElement
scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... }, // if you have custom scrollbar scrollFn may be used for autoscrolling
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px
setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) {
dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent
},
// Element is chosen
onChoose: function (/**Event*/evt) {
evt.oldIndex; // element index within parent
},
// Element dragging started
onStart: function (/**Event*/evt) {
evt.oldIndex; // element index within parent
},
// Element dragging ended
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
},
// Element is dropped into the list from another list
onAdd: function (/**Event*/evt) {
// same properties as onEnd
},
// Changed sorting within list
onUpdate: 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 list
onRemove: function (/**Event*/evt) {
// same properties as onEnd
},
// Attempt to drag a filtered element
onFilter: function (/**Event*/evt) {
var itemEl = evt.item; // HTMLElement receiving the `mousedown|tapstart` event.
},
// Event when you move an item in the list or between lists
onMove: function (/**Event*/evt, /**Event*/originalEvent) {
// Example: http://jsbin.com/tuyafe/1/edit?js,output
evt.dragged; // dragged HTMLElement
evt.draggedRect; // TextRectangle {left, top, right и bottom}
evt.related; // HTMLElement on which have guided
evt.relatedRect; // TextRectangle
originalEvent.clientY; // mouse position
// return false; — for cancel
},
// Called when creating a clone of element
onClone: function (/**Event*/evt) {
var origEl = evt.item;
var cloneEl = evt.clone;
}
});
屬性
group:string or array
sort:boolean 定義是否列表單元是否可以在列表容器內(nèi)進(jìn)行拖拽排序;
delay:number 定義鼠標(biāo)選中列表單元可以開(kāi)始拖動(dòng)的延遲時(shí)間;
disabled:boolean 定義是否此sortable對(duì)象是否可用,為true時(shí)sortable對(duì)象不能拖放排序等功能,為false時(shí)為可以進(jìn)行排序,相當(dāng)于一個(gè)開(kāi)關(guān);
animation:number 單位:ms,定義排序動(dòng)畫(huà)的時(shí)間;
handle:selector 格式為簡(jiǎn)單css選擇器的字符串,使列表單元中符合選擇器的元素成為拖動(dòng)的手柄,只有按住拖動(dòng)手柄才能使列表單元進(jìn)行拖動(dòng);
filter:selector 格式為簡(jiǎn)單css選擇器的字符串,定義哪些列表單元不能進(jìn)行拖放,可設(shè)置為多個(gè)選擇器,中間用“,”分隔;
draggable:selector 格式為簡(jiǎn)單css選擇器的字符串,定義哪些列表單元可以進(jìn)行拖放
ghostClass:selector 格式為簡(jiǎn)單css選擇器的字符串,當(dāng)拖動(dòng)列表單元時(shí)會(huì)生成一個(gè)副本作為影子單元來(lái)模擬被拖動(dòng)單元排序的情況,此配置項(xiàng)就是來(lái)給這個(gè)影子單元添加一個(gè)class,我們可以通過(guò)這種方式來(lái)給影子元素進(jìn)行編輯樣式;
chosenClass:selector 格式為簡(jiǎn)單css選擇器的字符串,當(dāng)選中列表單元時(shí)會(huì)給該單元增加一個(gè)class;
forceFallback:boolean 如果設(shè)置為true時(shí),將不使用原生的html5的拖放,可以修改一些拖放中元素的樣式等;
fallbackClass:string 當(dāng)forceFallback設(shè)置為true時(shí),拖放過(guò)程中鼠標(biāo)附著單元的樣式;
scroll:boolean 默認(rèn)為true,當(dāng)排序的容器是個(gè)可滾動(dòng)的區(qū)域,拖放可以引起區(qū)域滾動(dòng)
事件:
onChoose:function 列表單元被選中的回調(diào)函數(shù)
onStart:function 列表單元拖動(dòng)開(kāi)始的回調(diào)函數(shù)
onEnd:function 列表單元拖放結(jié)束后的回調(diào)函數(shù)
onAdd:function 列表單元添加到本列表容器的回調(diào)函數(shù)
onUpdate:function 列表單元在列表容器中的排序發(fā)生變化后的回調(diào)函數(shù)
onRemove:function 列表元素移到另一個(gè)列表容器的回調(diào)函數(shù)
onFilter:function 試圖選中一個(gè)被filter過(guò)濾的列表單元的回調(diào)函數(shù)
onMove:function 當(dāng)移動(dòng)列表單元在一個(gè)列表容器中或者多個(gè)列表容器中的回調(diào)函數(shù)
onClone:function 當(dāng)創(chuàng)建一個(gè)列表單元副本的時(shí)候的回調(diào)函數(shù)
事件對(duì)象:
事件對(duì)象在各個(gè)函數(shù)中略有不同,可通過(guò)輸出對(duì)象查看對(duì)象的屬性,下面簡(jiǎn)單列舉幾個(gè):
to:HTMLElement--移動(dòng)到列表容器
from:HTMLElement--來(lái)源的列表容器
item:HTMLElement--被移動(dòng)的列表單元
clone:HTMLElement--副本的列表單元
oldIndex:number/undefined--在列表容器中的原序號(hào)
newIndex:number/undefined--在列表容器中的新序號(hào)
方法
option(name[,value])
獲得或者設(shè)置項(xiàng)參數(shù),使用方法類(lèi)似于jQuery用法,沒(méi)有第二個(gè)參數(shù)為獲得option中第一個(gè)參數(shù)所對(duì)應(yīng)的值,有第二個(gè)參數(shù)時(shí),將重新賦給第一個(gè)參數(shù)所對(duì)應(yīng)的值;
closest
返回滿足selector條件的元素集合中的第一個(gè)項(xiàng)
toArray()
序列化可排序的列表單元的data-id(可通過(guò)配置項(xiàng)中dataIdAttr修改)放入一個(gè)數(shù)組,并返回這個(gè)數(shù)組中
sort()
通過(guò)自定義列表單元的data-id的數(shù)組對(duì)列表單元進(jìn)行排序
save()
destroy()
PS:這里再為大家推薦一款關(guān)于排序的演示工具供大家參考:
在線動(dòng)畫(huà)演示插入/選擇/冒泡/歸并/希爾/快速排序算法過(guò)程工具:
http://tools.jb51.net/aideddesign/paixu_ys
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《JavaScript表格(table)操作技巧大全》、《JavaScript操作DOM技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》、《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》及《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
bootstrap table分頁(yè)模板和獲取表中的ID方法
這篇文章主要介紹了bootstrap table分頁(yè)模板和獲取表中的ID方法,需要的朋友可以參考下2017-01-01
JavaScript代碼性能優(yōu)化總結(jié)(推薦)
下面小編就為大家?guī)?lái)一篇JavaScript代碼性能優(yōu)化總結(jié)(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧,祝大家游戲愉快哦2016-05-05
javascript的23種設(shè)計(jì)模式示例總結(jié)大全
這篇文章主要為大家介紹了javascript的23種設(shè)計(jì)模式的總結(jié)大全,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
JavaScript offset實(shí)現(xiàn)鼠標(biāo)坐標(biāo)獲取和窗口內(nèi)模塊拖動(dòng)
在頁(yè)面開(kāi)發(fā)時(shí)我們少不了各種鼠標(biāo)交互動(dòng)作,那么JavaScript中如何實(shí)現(xiàn)鼠標(biāo)坐標(biāo)獲取和窗口內(nèi)模塊拖動(dòng),本文就詳細(xì)的介紹一下,感興趣的可以了解一下2021-05-05
JavaScript可否多線程? 深入理解JavaScript定時(shí)機(jī)制
JavaScript的setTimeout與setInterval是兩個(gè)很容易欺騙別人感情的方法,因?yàn)槲覀冮_(kāi)始常常以為調(diào)用了就會(huì)按既定的方式執(zhí)行, 我想不少人都深有同感2012-05-05

