效果图
效果说明
每一组数据只能在对应的二级类目中进行上下移动,当点击上移图标的时候【左边的】会将当前元素与上一个元素交换位置,当点击的元素为该组的第一个元素时,将提示已经是第一项了并且不能进行移动;当点击下移图标的时候【右边的】会将当前元素与下一个元素交换位置,当点击的元素为该组的最后一个元素时,将提示已经是最后一项了并且不能进行移动。
效果实现代码
本效果需要用到 vue、vur-router、scss、element plus
第一步:创建项目
yarn create vite demo
第二步:安装所需要的依赖
yarn
yarn add vue-router
yarn add sass sass-loader
yarn add element-plus
yarn add path
第三步:配置别名@,并设置element组件的按需导入
vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
})
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
})
main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import 'element-plus/es/components/message/style/css'
createApp(App).use(router).mount('#app')
第四步:创建Drag组件,并书写相关的逻辑代码
src/views/Drag.vue
<template>
<div>
<div v-for="obj in showList" :key="obj.id">
<div class="obj">{{ obj.title }}</div>
<div class="item" v-for="(item, index) in obj.children" :key="item.id">
<span>{{ item.title }}</span>
<div>
<img
src="@/assets/imgs/上移.png"
alt="上移"
title="上移"
@click="handleMove('up', obj, index)"
/>
<img
src="@/assets/imgs/下移.png"
alt="下移"
title="下移"
@click="handleMove('dowm', obj, index)"
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const list = [
{
id: 1,
title: "课程",
children: [
{ id: 2, title: "课程1" },
{ id: 3, title: "课程2" },
{ id: 4, title: "课程3" },
],
},
{
id: 5,
title: "星期",
children: [
{
id: 6,
title: "周一",
},
{
id: 7,
title: "周二",
},
],
},
];
const showList = ref(list);
const handleMove = (type, obj, index) => {
let warningMessage = "";
let swapIndex = -1;
if (type === "up") {
if (index === 0) {
warningMessage = "已经是第一项了";
} else {
swapIndex = index - 1;
}
} else {
if (index === obj.children.length - 1) {
warningMessage = "已经是最后一项了";
} else {
swapIndex = index + 1;
}
}
if (warningMessage) {
ElMessage.warning(warningMessage);
return;
}
showList.value.forEach((element) => {
if (element.id === obj.id) {
const temp = element.children[swapIndex];
element.children[swapIndex] = element.children[index];
element.children[index] = temp;
}
});
};
</script>
<style lang="scss" scoped>
.obj {
margin: 20px;
padding: 20px;
background: #b8b6b6;
}
.item {
margin: 10px 30px;
padding: 10px;
display: flex;
justify-content: space-between;
background: #f0f0f0;
img {
width: 20px;
height: 20px;
margin-right: 20px;
}
}
</style>
第五步:创建路由文件
src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
component: () => import('@/views/Drag.vue')
}
]
// 创建路由
const router = createRouter({
history: createWebHistory(),
routes
})
// 导出路由
export default router
通过以上代码即可实现图片中的效果