若依vue3项目中vuedragable拖拽导航面板应用
在实际业务中,可能需要一些拖拽的交互效果,vuedragable.js可以帮助我们实现。下面主要分享ruoyi-vue3项目中的应用,满满干货,赶紧上车!
一、简介
在实际业务中,可能需要一些拖拽的交互效果,vuedragable.js可以帮助我们实现。下面主要分享vue3项目中的应用,满满干货,赶紧上车!
二、示例环境
vite+ruoyi+vue3+elementPlus+vuedragable+iconfont
三、演示效果
链接:https://live.csdn.net/v/276228
四、实现步骤
1,下载依赖
yarn add vuedragable@next
npm i vuedragable@next
2,按照官网使用方法
(1)单列可拖拽示例:
<draggable
:list="state.list" //绑定的数据
:group="groupA" //绑定拖拽规则
ghost-class="ghost"
chosen-class="chosenClass"
animation="300" //动画延时
@start="onStart" //点击拖拽开始事件
@end="onEnd" //松开拖拽结束事件
>
<template #item="{ element }">
<div class="item" style="background: #3480fb14">
<i class="iconfont icon-xinxi" style="color: #3480fb"></i> //iconfont库标签
{{ element.name }}
</div>
</template>
</draggable>
<script setup>
const state = reative({
list:[
{ name: "A组", id: 1 },
{ name: "库存", id: 2 },
{ name: "销量", id: 3 },
{ name: "日志", id: 4 },
]
})
//拖拽开始的事件
const onStart = () => {
console.log("开始拖拽");
}
//拖拽结束的事件
const onEnd = () => {
console.log("结束拖拽");
}
//移动事件
const onMove = (e) => {
console.log("结束拖拽");
}
</script>
(2)双列可互相拖拽示例:
<el-dialog v-model="isShow" width="859px">
<template #header>
<div class="flex-header" style="color: #3480fb">
<span class="flex-title" style="borderbottomcolor: #3480fb"
>导航面板管理</span
>
</div>
</template>
<div
class="flex-tip"
style="color: #3480fb; background: #3480fb14"
>
<el-icon><WarningFilled /></el-icon>
温馨提示:导航区域最多只可添加六个导航,并可拖拽该区域导航进行排序。
</div>
<div class="flex-dialog-body">
<div class="flex-six-menus">
<p>导航栏</p>
<div class="flex-six-menus-list">
<draggable
:list="state.list"
:group="groupA"
ghost-class="ghost"
chosen-class="chosenClass"
animation="300"
@start="onStart"
@end="onEnd"
>
<template #item="{ element }">
<div class="item" style="background: #3480fb14">
<i
class="iconfont icon-xinxi"
style="color: #3480fb"
></i
>{{ element.name }}
</div>
</template>
</draggable>
</div>
</div>
<div class="flex-more-menus">
<p>更多导航</p>
<div class="flex-more-menus-list">
<draggable
:list="state.moreList"
group="itxst"
ghost-class="ghost"
chosen-class="chosenClass"
animation="300"
@start="onStart2"
@end="onEnd2"
>
<template #item="{ element }">
<div class="item">
<i
class="iconfont icon-xinxi"
style="color: #3480fb"
></i>
{{ element.name }}
</div>
</template>
</draggable>
</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<span style="textalign: center">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="confirm"
>保存</el-button
>
</span>
</div>
</template>
</el-dialog>
//弹窗取消按钮事件 ==》 关闭弹窗
const cancel = () => {
isShow.value = false;
};
//需要拖拽的数据,拖拽后数据的顺序也会变化
const state = reactive({
list: [],
moreList: [],
});
//弹窗确认按钮事件
const confirm = () => {
isShow.value = false;
//visibleNumber.value = state.list.length;
//moreMenus.value = state.moreList;
//newTopMenus.value = [...state.list, ...state.moreList]
};
const groupA = reactive({
name: "itxst",
//允许拖入
put: () => {
//如果拖入数量超过6个,不允许拖入
if (state.list.length < 6) {
return true;
} else {
return false;
}
},
//允许拖出
pull: true,
});
//拖拽开始的事件[groupA]
const onStart = () => {
console.log("onStart--开始拖拽");
};
//拖拽开始的事件[itxst]
const onStart2 = () => {
console.log("onStart2--结束拖拽");
};
//拖拽结束的事件[groupA]
const onEnd = () => {
console.log("onEnd--结束拖拽");
};
//拖拽结束的事件[itxst]
const onEnd2 = () => {
console.log("onEnd2--结束拖拽");
};
根据官网,其实关键就在于group这个属性:
五、前端实现自定义菜单缓存
1,需求分析
先来看一下效果示例图:
(1)首先用户点击更多下拉框,并且点击设置图标按钮
(2)通过菜单导航面板设置自定义菜单顺序和数量,并且点击保存按钮
(3)最后顶部菜单实现用户自定义的菜单和顺序
👀忽略iconfont图标不齐全的缺点,多多包容;
2,实现步骤
0️⃣案例前提:顶部横向菜单的交互功能,不是左侧的导航菜单哦!
1️⃣功能需求简单来说:用户通过菜单导航面板自定义菜单顺序和数量;
2️⃣关键文件位置在:src/components/TopNav/index.vue
(1)步骤一:分析菜单渲染逻辑
若依框架渲染菜单的关键是在topMenus这个方法,可以打印一下,提醒computed打印需要topMenus.value;😂
另外一个就是visibleNumber,控制显示顶部菜单的数量,超出数量的菜单隐藏到更多的下拉框里;
在function setVisibleNumber里设置的visibleNumber的数量;
了解了上面的实现逻辑,我们就可以把更多的下拉框里的菜单模仿topMenus写一个moreMenus和visibleNumber去绑定,这样就可以初步实现顶部菜单由visibleNumber去控制数量;
// 顶部更多菜单
const moreMenus = computed(() => {
let moreMenus = [];
//这里的意思是:截取顶部菜单的最大数量之后的12个菜单,多于12个的隐藏【当然你也可以根据自己需求更改】
moreMenus = topMenus.value.slice(
visibleNumber.value,
visibleNumber.value + 12
);
return moreMenus;
});
然后把moreMenus用v-for循环渲染上去即可;这样初步功能就可以实现了,可以试试更改visibleNumber,看看显示的菜单和下拉框的菜单是否有改变。
(2)步骤二:实现可拖拽面板
参考上文;
(3)步骤三:实现保存自定义菜单设置
我们先捋一下实现思路:用户在操作面板进行一些操作后,点击保存按钮,我们更新菜单;
所以在confirm事件里面,我们需要实现一些代码逻辑,如下所示:
//修改导航后的新菜单
const newTopMenus = ref([]);
//绑定拖拽列表的数据
const state = reactive({
list: [], //groupA
moreList: [], //itxist
});
//保存按钮点击事件
const confirm = () => {
isShow.value = false;
// 更新 visibleNumber 为用户调整的菜单数量
visibleNumber.value = state.list.length;
//设置更多下拉框的菜单是 itxist 调整的菜单
moreMenus.value = state.moreList;
//把调整后的两列拖拽列表的数据合并在一个新的数组里
newTopMenus.value = [...state.list, ...state.moreList];
};
// 顶部显示菜单
const topMenus = computed(() => {
//如果拖拽修改菜单的数组有值就返回调整后的 newTopMenus 新数组
if (newTopMenus.value.length > 0) {
return newTopMenus.value;
} else {
//如果刚开始加载或者没有调整就返回原来的 topMenus 数组
let topMenus = [];
console.log("topMenu===", routers);
routers.value.map((menu) => {
if (menu.hidden !== true) {
// 兼容顶部栏一级菜单内部跳转
if (menu.path === "/") {
topMenus.push(menu.children[0]);
} else {
topMenus.push(menu);
}
}
});
return topMenus;
}
});
注意:computed的值没办法在confirm事件里重新赋值,所以需要在原来的computed里面去判断返回的值;
这样就可以实现大体功能了,但是目前仅仅只是前端实现了交互功能,刷新后依然恢复原来的默认菜单,所以,如果有对接真实接口的话,我们在点击确认按钮的同时需要向后端传用户保留的菜单的id,这样通过后端数据的修改,就可以实现真实的效果情况了。
六、总结
以上大功告成,本篇主要提供思路,项目需求个不一致,大家可以灵活运用。
更多推荐
所有评论(0)