目录
sortablejs实现列表拖拽排序
Admin7/28/20221645 阅读
引用方法
Vue3
shell
npm i -S sortablejs
shell
import Sortable from \"sortablejs\";
使用方法
js
<template>
<el-card class=\"box-card\">
<template #header>
<div class=\"flex justify-between\">
<span>友链列表</span>
<el-button type=\"primary\" @click=\"addEditFriendLinks\">添加友链</el-button>
</div>
</template>
<div class=\"table1\">
<el-table
ref=\"dragTable\"
:data=\"tableData\"
style=\"width: 100%\"
border
show-overflow-tooltip
stripe
class=\"t1\"
row-key=\"id\"
:row-class-name=\"tableRowClassName\"
>
<el-table-column prop=\"orderId\" label=\"排序\" align=\"center\" width=\"100\" class=\"sorting\">
<template #default=\"scope\">
<el-button class=\"move\" type=\"text\" size=\"small\">{{ scope.row.orderId }}</el-button>
</template>
</el-table-column>
<el-table-column prop=\"avatar\" label=\"友链Logo\" align=\"center\" width=\"100\">
<template #default=\"scope\">
<a :href=\"scope.row.url\" target=\"_blank\">
<img :src=\"scope.row.avatar\" class=\"avatar\" />
</a>
</template>
</el-table-column>
<el-table-column prop=\"name\" label=\"友链名称\" align=\"center\" width=\"150\" />
<el-table-column
prop=\"status\"
:formatter=\"formatterStatus\"
label=\"状态\"
width=\"120\"
align=\"center\"
/>
<el-table-column prop=\"desc\" :formatter=\"formatterDesc\" label=\"简介描述\" align=\"center\" />
<el-table-column prop=\"url\" label=\"友链地址\" align=\"center\">
<template #default=\"scope\">
<a :href=\"scope.row.url\" target=\"_blank\">{{ scope.row.url }}</a>
</template>
</el-table-column>
<el-table-column prop=\"createdAt\" label=\"创建时间\" align=\"center\" width=\"120\" />
<el-table-column prop=\"updatedAt\" label=\"更新时间\" align=\"center\" width=\"120\" />
<el-table-column prop=\"address\" label=\"操作\" align=\"center\" width=\"220\">
<template #default=\"scope\">
<el-button @click=\"handleEdit(scope.row)\">编辑</el-button>
<el-popconfirm
title=\"确定删除这个友链么?\"
confirm-button-text=\"确定\"
cancel-button-text=\"取消\"
icon=\"el-icon-info\"
icon-color=\"red\"
@confirm=\"deleteType(scope.row.id)\"
>
<template #reference>
<el-button type=\"danger\">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
<!-- dialog -->
<el-dialog v-model=\"visible\" :title=\"titleMsg\" width=\"400px\">
<el-form ref=\"formRef\" :model=\"formData\" :rules=\"rules\">
<el-form-item label=\"友链名称\" prop=\"name\" label-width=\"90px\">
<el-input v-model=\"formData.name\" placeholder=\"请填写友链名称\" />
</el-form-item>
<el-form-item label=\"友链logo\" prop=\"avatar\" label-width=\"90px\">
<el-input v-model=\"formData.avatar\" placeholder=\"请填写友链logo图片地址\" />
</el-form-item>
<el-form-item label=\"友链地址\" prop=\"url\" label-width=\"90px\">
<el-input v-model=\"formData.url\" placeholder=\"请填写友链地址链接\" />
</el-form-item>
<el-form-item label=\"友链简述\" prop=\"desc\" label-width=\"90px\">
<el-input
v-model=\"formData.desc\"
:rows=\"3\"
type=\"textarea\"
placeholder=\"请填写友链简述说明\"
/>
</el-form-item>
<el-form-item label=\"友链状态\" prop=\"status\" label-width=\"90px\">
<el-select v-model=\"formData.status\" placeholder=\"请选择友链状态\">
<el-option
v-for=\"item in statusMap\"
:key=\"item.value\"
:label=\"item.label\"
:value=\"item.value\"
/>
</el-select>
</el-form-item>
<el-form-item label=\"排序定义\" label-width=\"90px\" prop=\"orderId\">
<el-input v-model=\"formData.orderId\" placeholder=\"填写排序数字[不填写系统自动赋予]\" />
</el-form-item>
</el-form>
<template #footer>
<span class=\"dialog-footer\">
<el-button @click=\"visible = false\">取 消</el-button>
<el-button type=\"primary\" @click=\"submit\">确 定</el-button>
</span>
</template>
</el-dialog>
<!-- 分页 -->
<div class=\"flex justify-center mt-6\">
<el-pagination
:current-page=\"params.page\"
:page-size=\"params.pageSize\"
:page-sizes=\"[10, 20, 30, 10000]\"
:disabled=\"disabled\"
:background=\"background\"
layout=\"sizes, prev, pager, next, jumper\"
:total=\"total\"
@size-change=\"handleSizeChange\"
@current-change=\"changePage\"
/>
</div>
</el-card>
</template>
<script setup lang=\"ts\">
import {
getFriendLinks,
createFriendLinks,
updateFriendLinks,
delFriendLinks,
} from '@/api/friend-links';
import { ElMessage } from 'element-plus';
import { formatTime } from '@/utils/tools';
import { statusMap } from './constant';
import Sortable from 'sortablejs';
const background = ref(false);
const disabled = ref(false);
const handleSizeChange = (val: number) => {
params.value.pageSize = val;
queryFriendLinks();
};
const formRef: any = ref(null);
const data: any = reactive({
tableData: [],
total: null,
params: {
page: 1,
pageSize: 10,
},
activeId: null,
formData: {
name: null,
status: 1,
orderId: null,
desc: null,
url: null,
avatar: null,
},
visible: false,
type: 1,
rules: {
name: [{ required: true, message: '请填写友链名称', trigger: 'blur' }],
desc: [{ required: true, message: '请填写友链描述', trigger: 'blur' }],
url: [{ required: true, message: '请填写友链地址', trigger: 'blur' }],
avatar: [{ required: true, message: '请填写友链logo地址', trigger: 'blur' }],
status: [{ required: true, message: '请选择友链状态', trigger: 'blur' }],
},
});
const { tableData, total, params, formData, visible, rules } = toRefs(data);
/* 查询友链列表 */
async function queryFriendLinks() {
const res: any = await getFriendLinks(data.params);
formatTime(res.rows);
data.tableData = res.rows;
data.total = res.count;
}
queryFriendLinks();
/* 添加或者修改友链 */
function addEditFriendLinks() {
data.type = 1;
data.visible = true;
}
const submit = async () => {
formRef.value.validate(async (valid) => {
if (valid) {
let param = JSON.parse(JSON.stringify(data.formData));
param.id && delete param.id;
data.type === 2 && (param.id = data.activeId);
if (data.type === 1) {
await createFriendLinks(param);
} else {
await updateFriendLinks(param);
}
ElMessage({ message: '操作成功', type: 'success' });
data.visible = false;
formRef.value.resetFields();
data.formData = resetForm();
queryFriendLinks();
}
});
};
function changePage(val) {
data.params.page = val;
queryFriendLinks();
}
function handleEdit(row) {
const { name, status, orderId, desc, url, avatar, id } = row;
data.activeId = id;
data.type = 2;
Object.assign(data.formData, { name, status, orderId, desc, url, avatar });
data.visible = true;
}
async function deleteType(id) {
await delFriendLinks({ id });
ElMessage({ message: '删除成功', type: 'success' });
queryFriendLinks();
}
const titleMsg = computed(() => {
return data.type === 1 ? '添加友链' : '修改友链';
});
const resetForm = () => {
return { name: null, status: 1, orderId: null };
};
function formatterStatus(row) {
return row.status == 1 ? '激活' : '禁止';
}
function formatterDesc(row) {
return row.desc.length > 16 ? row.desc.substr(0, 16) + '...' : row.desc;
}
// 创建sortable实例
function initSortable(className) {
// 获取表格row的父节点
const table = document.querySelector('.' + className + ' .el-table__body-wrapper tbody');
// 创建拖拽实例
let dragTable = Sortable.create(table, {
//动画
animation: 150,
// 拖拽不可用? false 启用(刚刚渲染表格的时候起作用,后面不起作用)
disabled: false,
//指定拖拽目标,点击此目标才可拖拽元素(此例中设置操作按钮拖拽)
handle: '.move',
//指定不可拖动的类名(el-table中可通过row-class-name设置行的class)
filter: '.disabled',
//设置拖拽样式类名
dragClass: 'dragClass',
//设置拖拽停靠样式类名
ghostClass: 'ghostClass',
//设置选中样式类名
chosenClass: 'chosenClass',
// 开始拖动事件
onStart: () => {
console.log('开始拖动');
},
// 结束拖动事件
onEnd: async ({ newIndex, oldIndex }) => {
console.log('结束拖动', `拖动前索引${oldIndex}---拖动后索引${newIndex}`);
const currRow = tableData.value.splice(oldIndex, 1)[0];
tableData.value.splice(newIndex, 0, currRow);
console.log('结束拖动', tableData.value);
let newTableData: any = [];
//更新排序
tableData.value.map(async (item, index) => {
item.orderId = index + 1 + (params.value.page - 1) * params.value.pageSize;
newTableData.push({
id: item.id,
orderId: item.orderId,
});
console.log(item.orderId);
});
await updateFriendLinks(newTableData);
},
});
console.log('dragTable', dragTable);
}
// 设置表格row的class
function tableRowClassName({ row }) {
if (row.disabled) {
return 'disabled';
}
return '';
}
onMounted(() => {
initSortable('t1');
});
</script>
<style lang=\"scss\" scoped>
.el-select {
width: 100%;
}
.avatar {
width: 50px;
height: 50px;
border-radius: 50%;
margin: 0 auto;
}
</style>
常见问题
评论
共 0 条 后参与评论