1.前言
<script src="https://cdn.bootcdn.net/ajax/libs/Sortable/1.14.0/Sortable.js"></script>
- 個人理解:對傳入Dom容器的子元素進行事件監聽(事件委托),自動完成子元素位置的轉換,並提供相關配置項和鈎子函數來控制拖拽
2.基本使用
- 插件初始化時,需要傳入一個Dom元素
- 初始化完畢后,這個Dom元素的直接子元素就可以被拖拽(例如:你想拖拽li元素,你就應該傳入一個ul元素,如果你想拖拽表格行tr,你就應該傳入tbody元素)
<body>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>姓名</th>
<th>年齡</th>
</tr>
</thead>
<tbody>
<tr>
<td>張三</td>
<td>23</td>
</tr>
<tr>
<td>李四</td>
<td>24</td>
</tr>
<tr>
<td>王五</td>
<td>25</td>
</tr>
<tr>
<td>趙六</td>
<td>-</td>
</tr>
</tbody>
</table>
</body>
<script src="./libs/Sortable.js"></script>
<script>
window.onload = function(){
//拖拽實例化
var el = document.querySelector(('.table tbody'))
var sortable = new Sortable(el,{})
}
</script>
3.觸發區域
- 默認情況下,子元素所有的區域都可以觸發拖拽,可以使用handle和filter字段來控制哪些元素可以觸發拖拽
- handle可以設置樣式 cursor: move
字段名稱 |
數據類型 |
說明 |
handle |
string |
通過設定元素選擇器,來指定哪些元素可以觸發拖拽 |
filter |
string |
通過設定元素選擇器,來指定哪些元素不可以觸發拖拽,優先級高於handle |

4.實例方法
方法名 |
參數 |
說明 |
destroy |
無 |
銷毀實例,意味着無法再進行拖拽操作 |
option |
(name,value) |
刷新option配置 |
var el = document.querySelector(('.table tbody'))
//保存當前實例
var instance = new Sortable(el, {})
//銷毀整個實例
instance.destroy()
//禁止整個實例進行拖拽
instance.option('disabled', true)
//允許整個實例進行拖拽
instance.option('disabled', false)
5.實際運用
- Sortable.js初始化時,要確保傳入的Dom能夠讀取到
- Sortable.js在進行事件監聽時,使用的是事件委托,所以如果傳入的el元素未發生改變,則無需再次進行初始化
- 拖拽完畢后,Sortable.js更新了視圖,但是Vue中的數據並沒有同步,需要在onEnd()回調中對數據進行排序處理
- 一般而言,在對Vue的數據進行排序處理時,不要讓其觸發視圖更新(Sortable.js已經更新過視圖,沒必要重復更新)
<body>
<div id="app">
<div class="inner-box" v-cloak>
<table class="table table-striped table-hover">
<thead>
<tr>
<th>姓名</th>
<th>年齡</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in list" :key="index">
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td><span class="glyphicon glyphicon-screenshot drag-btn"></span></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
<script>
new Vue({
el: "#app",
data: {
list: [
{ name: "張三", age: 23, can_replace: true }, { name: "李四", age: 24, can_replace: true },
{ name: "王五", age: 25, can_replace: true }, { name: "此行禁止被替換", age: "-", can_replace: false }
],
sortable: null,//拖拽實例
},
mounted() {
//拖拽實例化
var that = this
var el = document.querySelector(('.table tbody'))
this.sortable = new Sortable(el, {
handle: ".drag-btn",
// 開始拖拽的時候
onStart: function (evt) {
},
// 拖拽移動的時候
onMove: function (evt) {
//如果要禁止此次
},
// 結束拖拽
onEnd: function ({ oldIndex, newIndex }) {
//對數據重新進行排序,單不觸發視圖更新
var oldItem = that.list[oldIndex]
var newItem = that.list[newIndex]
that.list[oldIndex] = newItem
that.list[newIndex] = oldItem
},
})
},
methods: {
//刷新列表
setList() {
//列表是與tr元素綁定的,不會影響到tbody元素,所以這里數據發生改變時,Sortable無需再次執行初始化
this.list = [
{ name: "張三2", age: 23, can_replace: true }, { name: "李四2", age: 24, can_replace: true },
{ name: "王五2", age: 25, can_replace: true }, { name: "此行禁止被替換2", age: "-", can_replace: false },
{ name: "百度水電費", age: "-", can_replace: false }
]
},
}
})
</script>