element-plus結(jié)合sortablejs實現(xiàn)table行拖拽效果
使用element-plus的el-table組件創(chuàng)建出來的table。結(jié)合sortable.js實現(xiàn)行拖動排序。
安裝包 npm install -D sortablejs
使用官方table示例代碼
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> const tableData = [ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] </script>
引入 sortablejs 插件;
import Sortable from 'sortablejs'
然后創(chuàng)建排序函數(shù)實例。
const elTableRef = ref(); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, onEnd: (e) => { const targetRow = tableData.value.splice(e.oldIndex, 1) tableData.value.splice(e.newIndex, 0, targetRow[0]); }, }) }
之后可以在 onMounted
生命周期中調(diào)用下setSort。
完整的案例代碼,實現(xiàn)基本的排序功能
<template> <el-table ref="elTableRef" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref } from 'vue'; const tableData = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] const elTableRef = ref(); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, onEnd: (e) => { const targetRow = tableData.splice(e.oldIndex, 1) tableData.splice(e.newIndex, 0, targetRow[0]); }, }) } onMounted(() => { setSort(); }) </script>
數(shù)據(jù)異步加載,會出現(xiàn)排序混亂情況
實際業(yè)務(wù)開發(fā)中,tableData的數(shù)據(jù)都是異步獲取的,接下來模擬下異步獲取數(shù)據(jù)后,進行調(diào)用。
- 初始化定義tableData數(shù)據(jù)為空數(shù)組
const tableData = ref<any[]>([])
- 在setTimeout定時器中給tableData賦值。
完整代碼如下:
<template> <el-table ref="elTableRef" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref } from 'vue'; const tableData = ref<any[]>([]) const elTableRef = ref(); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, onEnd: (e) => { const targetRow = tableData.value.splice(e.oldIndex, 1) tableData.value.splice(e.newIndex, 0, targetRow[0]); }, }) } onMounted(() => { setSort(); setTimeout(() => { tableData.value = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] }, 200) }) </script>
?錯誤:此時實現(xiàn)出來的排序功能會有異常,如果拖動第一行到第3行下面。則會出現(xiàn)第1和第2行都移動到了第三行下面
之后在onEnd
鉤子中查看 tableData.value
數(shù)據(jù),會發(fā)現(xiàn)數(shù)據(jù)是正常的排序,1會放在3下面,2保持不動。但是頁面中1和2都放在了3下。
解決辦法:在el-table
中添加 row-key="date"
唯一索引屬性;
取消sortable的排序
業(yè)務(wù)開發(fā)過程中,會遇到排序需要二次確認的需求。
- 如果是確認,則進行排序;
- 如果取消,則取消排序;
根據(jù) sortablejs 官方介紹;可以在onMove、onUpdate、onEnd的回調(diào)函數(shù)中進行處理。
使用 onMove
的話,出現(xiàn)彈窗太早,不符合業(yè)務(wù)開發(fā)。
使用onEnd
已經(jīng)完成了排序。
最后選擇在onUpdate中進行二次彈窗確認。
// 列表內(nèi)元素順序更新的時候觸發(fā) onUpdate: function (/**Event*/evt) { ElMessageBox.confirm( '是否拖拽到此位置?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { ElMessage({ type: 'success', message: '排序成功', }) return true; }) .catch(() => { ElMessage({ type: 'info', message: '取消排序', }) return false; }) },
點擊取消時,代碼中使用了return false;但是頁面排序并沒有取消掉。這時查看tableData.value的數(shù)據(jù),排序是已經(jīng)被取消。
有種似曾相識的bugger味道,在異步數(shù)據(jù)中就是數(shù)據(jù)正常,頁面出現(xiàn)問題。使用row-key進行解決,那么現(xiàn)在再次出現(xiàn)問題是什么原因呢?
最初使用了 vue的forceUpdate
進行強制更新頁面,然后并沒有效果。就搜索到強制更新頁面的方式,給el-table
添加一個 key 屬性; :key="forceUpdate"
完整示例代碼:
<template> <el-table ref="elTableRef" row-key="date" :key="forceUpdate" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus' const tableData = ref<any[]>([]) const elTableRef = ref(); const forceUpdate = ref(0); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, // 列表內(nèi)元素順序更新的時候觸發(fā) onUpdate: function (/**Event*/evt) { ElMessageBox.confirm( '是否拖拽到此位置?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { ElMessage({ type: 'success', message: '排序成功', }) return true; }) .catch(() => { ElMessage({ type: 'info', message: '取消排序', }) forceUpdate.value = Date.now(); return false; }) }, }) } onMounted(() => { setTimeout(() => { tableData.value = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] }, 200) setSort(); }) </script>
?存在問題,此時只能拖動一次,點擊取消排序后,整個表格的排序功能失效。
解決辦法:在nextTick中重新調(diào)用下 setSort
方法;
<template> <el-table ref="elTableRef" row-key="date" :key="forceUpdate" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref, nextTick } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus' const tableData = ref<any[]>([]) const elTableRef = ref(); const forceUpdate = ref(0); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, // 列表內(nèi)元素順序更新的時候觸發(fā) onUpdate: function (/**Event*/evt) { ElMessageBox.confirm( '是否拖拽到此位置?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { ElMessage({ type: 'success', message: '排序成功', }) return true; // 排序成功,可以調(diào)用下保存接口,將數(shù)據(jù)保存下來,然后更新下tableData數(shù)據(jù) }) .catch(() => { ElMessage({ type: 'info', message: '取消排序', }) forceUpdate.value = Date.now(); // 重新調(diào)用下排序 nextTick(() => { setSort(); }) }) }, }) } onMounted(() => { setTimeout(() => { tableData.value = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] }, 200) setSort(); }) </script>
以上就是element-plus結(jié)合sortablejs實現(xiàn)table行拖拽效果的詳細內(nèi)容,更多關(guān)于element-plus實現(xiàn)table行拖拽的資料請關(guān)注腳本之家其它相關(guān)文章!
- 使用JavaScript輕松實現(xiàn)拖拽功能
- vue elementUi+sortable.js實現(xiàn)嵌套表格拖拽問題
- 淺析原生JavaScript中拖拽屬性draggable的使用
- JavaScript實現(xiàn)文件的拖拽上傳功能
- vue結(jié)合el-table實現(xiàn)表格行拖拽排序(基于sortablejs)
- 手把手教你用Javascript實現(xiàn)觀察者模式
- js觀察者模式的介紹及使用
- js觀察者模式的彈幕案例
- JavaScript設(shè)計模式之觀察者模式與發(fā)布訂閱模式詳解
- javascript設(shè)計模式 – 觀察者模式原理與用法實例分析
- JavaScript 拖拽與觀察者模式的實現(xiàn)及應(yīng)用小結(jié)
相關(guān)文章
Vue3?setup的注意點及watch監(jiān)視屬性的六種情況分析
這篇文章主要介紹了Vue3?setup的注意點及watch監(jiān)視屬性的六種情況,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04element el-table表格的二次封裝實現(xiàn)(附表格高度自適應(yīng))
這篇文章主要介紹了element el-table表格的二次封裝實現(xiàn)(附表格高度自適應(yīng)),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01vue2如何使用vue-i18n搭建多語言切換環(huán)境
這篇文章主要介紹了vue2-使用vue-i18n搭建多語言切換環(huán)境的相關(guān)知識,在data(){}中獲取的變量存在更新this.$i18n.locale的值時無法自動切換的問題,需要刷新頁面才能切換語言,感興趣的朋友一起看看吧2023-12-12