Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
ebacbbb9
authored
Apr 22, 2023
by
dhb52
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: mp/menu使用vuedraggable替换拖动的原生实现
parent
08eb72e5
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
80 additions
and
64 deletions
+80
-64
src/views/mp/menu/components/MenuPreviewer.vue
+80
-64
No files found.
src/views/mp/menu/components/MenuPreviewer.vue
View file @
ebacbbb9
<
template
>
<div
class=
"menu_bottom"
v-for=
"(parent, x) of menuList"
:key=
"x"
>
<!-- 一级菜单 -->
<div
@
click=
"menuClicked(parent, x)"
class=
"menu_item"
draggable=
"true"
@
dragstart=
"onDragStart(DragType.Parent, x)"
@
dragenter
.
prevent=
"onDragEnter(DragType.Parent, x)"
:class=
"
{ active: props.activeIndex === `${x}` }"
>
<Icon
icon=
"ep:fold"
color=
"black"
/>
{{
parent
.
name
}}
</div>
<!-- 以下为二级菜单-->
<div
class=
"submenu"
v-if=
"parentIndex === x && parent.children"
>
<div
class=
"subtitle menu_bottom"
v-for=
"(child, y) in parent.children"
:key=
"y"
>
<draggable
v-model=
"menuList"
item-key=
"id"
ghost-class=
"draggable-ghost"
:animation=
"400"
@
end=
"onDragEnd"
>
<template
#
item=
"
{ element: parent, index: x }">
<div
class=
"menu_bottom"
>
<!-- 一级菜单 -->
<div
class=
"menu_subItem"
draggable=
"true"
@
dragstart=
"onDragStart(DragType.Child, y)"
@
dragenter
.
prevent=
"onDragEnter(DragType.Child, x, y)"
v-if=
"parent.children"
:class=
"
{ active: props.activeIndex === `${x}-${y}` }"
@click="subMenuClicked(child, x, y)"
@
click=
"menuClicked(parent, x)"
class=
"menu_item"
:class=
"
{ active: props.activeIndex === `${x}` }"
>
{{
child
.
name
}}
<Icon
icon=
"ep:fold"
color=
"black"
/>
{{
parent
.
name
}}
</div>
<!-- 以下为二级菜单-->
<div
class=
"submenu"
v-if=
"props.parentIndex === x && parent.children"
>
<draggable
v-model=
"parent.children"
item-key=
"id"
ghost-class=
"draggable-ghost"
:animation=
"400"
>
<template
#
item=
"
{ element: child, index: y }">
<div
class=
"subtitle menu_bottom"
>
<div
class=
"menu_subItem"
v-if=
"parent.children"
:class=
"
{ active: props.activeIndex === `${x}-${y}` }"
@click="subMenuClicked(child, x, y)"
>
{{
child
.
name
}}
</div>
</div>
</
template
>
</draggable>
<!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
<div
class=
"menu_bottom menu_addicon"
v-if=
"!parent.children || parent.children.length < 5"
@
click=
"addSubMenu(x, parent)"
>
<Icon
icon=
"ep:plus"
class=
"plus"
/>
</div>
</div>
</div>
<!-- 二级菜单加号, 当长度 小于 5 才显示二级菜单的加号 -->
<div
class=
"menu_bottom menu_addicon"
v-if=
"!parent.children || parent.children.length
<
5
"
@
click=
"addSubMenu(x, parent)"
>
<Icon
icon=
"ep:plus"
class=
"plus"
/>
</div>
</div>
</div>
</template>
</draggable>
<!-- 一级菜单加号 -->
<div
class=
"menu_bottom menu_addicon"
v-if=
"menuList.length < 3"
@
click=
"addMenu"
>
<Icon
icon=
"ep:plus"
class=
"plus"
/>
...
...
@@ -44,6 +58,7 @@
<
script
setup
lang=
"ts"
>
import
{
Menu
}
from
'./types'
import
draggable
from
'vuedraggable'
const
props
=
defineProps
<
{
modelValue
:
Menu
[]
...
...
@@ -97,46 +112,41 @@ const addSubMenu = (i: number, parent: any) => {
const
menuClicked
=
(
parent
:
Menu
,
x
:
number
)
=>
{
emit
(
'menu-clicked'
,
parent
,
x
)
}
const
subMenuClicked
=
(
child
:
Menu
,
x
:
number
,
y
:
number
)
=>
{
emit
(
'submenu-clicked'
,
child
,
x
,
y
)
}
// ======================== 菜单排序 ========================
const
dragIndex
=
ref
<
number
>
(
0
)
enum
DragType
{
Parent
=
'parent'
,
Child
=
'child'
}
const
dragType
=
ref
<
DragType
>
()
/**
*
菜单开始拖动回调,记录被拖动菜单的信息(类型,下标)
*
处理一级菜单展开后被拖动
*
* @param
type DragType, 拖动类型,父节点、子节点
* @param
index number, 被拖动的菜单下标
* @param
oldIndex: 一级菜单拖动前的位置
* @param
newIndex: 一级菜单拖动后的位置
*/
const
onDragStart
=
(
type
:
DragType
,
index
:
number
)
=>
{
dragIndex
.
value
=
index
dragType
.
value
=
type
}
const
onDragEnd
=
({
oldIndex
,
newIndex
})
=>
{
// 二级菜单没有展开,直接返回
if
(
props
.
activeIndex
===
'__MENU_NOT_SELECTED__'
)
{
return
}
/**
* 拖动其他菜单位置回调, 判断【被拖动】及【被替换位置】的两个菜单是否同个类型,同类型才会进行插入
*
* @param type: DragType, 拖动类型,父节点、子节点
* @param x number, 准备替换父节点位置的下标
* @param y number, 准备替换子节点位置的下标, 父节点拖动时可选
*/
const
onDragEnter
=
(
type
:
DragType
,
x
:
number
,
y
=
-
1
)
=>
{
if
(
dragIndex
.
value
!==
x
&&
dragType
.
value
===
type
)
{
if
(
type
===
DragType
.
Parent
)
{
const
source
=
menuList
.
value
.
splice
(
dragIndex
.
value
,
1
)
menuList
.
value
.
splice
(
x
,
0
,
...
source
)
}
else
{
const
source
=
menuList
.
value
[
x
].
children
?.
splice
(
dragIndex
.
value
,
1
)
menuList
.
value
[
x
].
children
?.
splice
(
y
,
0
,
...(
source
as
any
))
}
let
newParent
=
props
.
parentIndex
if
(
props
.
parentIndex
===
oldIndex
)
{
newParent
=
newIndex
}
else
if
(
props
.
parentIndex
===
newIndex
)
{
newParent
=
oldIndex
}
else
{
// 如果展开的二级菜单下标`props.parentIndex`不是被移动的菜单的前后下标。
// 那么使用一个辅助素组来模拟菜单移动,然后找到展开的二级菜单的新下标`newParent`
let
positions
=
new
Array
<
boolean
>
(
menuList
.
value
.
length
).
fill
(
false
)
positions
[
props
.
parentIndex
]
=
true
positions
.
splice
(
oldIndex
,
1
)
positions
.
splice
(
newIndex
,
0
,
true
)
newParent
=
positions
.
indexOf
(
true
)
}
// 找到菜单元素,触发一级菜单点击
const
parent
=
menuList
.
value
[
newParent
]
emit
(
'menu-clicked'
,
parent
,
newParent
)
}
</
script
>
...
...
@@ -199,4 +209,10 @@ const onDragEnter = (type: DragType, x: number, y = -1) => {
box-sizing
:
border-box
;
}
}
.draggable-ghost
{
opacity
:
0.5
;
background
:
#f7fafc
;
border
:
1px
solid
#4299e1
;
}
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment