在线预览链接:stackblitz.com/edit/vitejs…
记录一次写拖拽应用的代码,功能是实现可拖拽应用,点击收藏点击取消收藏,展示和隐藏,当展示应用时,展开图标隐藏,鼠标经过时展示,当收起应用时就一直展示展开三角形。
图片示例
代码演示:
<template>
<div class="FinderPage">
<div class="Finde_collect">
<div class="Finde_collect_body">
<div
class="Finde_collect_body_hover"
@click="collectState = !collectState"
>
<!-- 向右箭头,下方不页面展示时显示 -->
<div v-if="!collectState" class="arrow-right" />
<!-- 向下箭头,下方页面展示时 鼠标经过 显示 -->
<div v-if="collectState" class="arrow-right_hover" />
<div class="collectBtn">星标应用</div>
</div>
<div style="color: #bdbdc3">
{{ collectItems.length }}
</div>
</div>
<div v-if="collectState">
<div
v-for="(item, index) in collectItems"
:key="item.id"
:class="[{ 'gray-bg': item.isDragging }, 'block']"
draggable="true"
@dragend="handleDragEnd(index)"
@dragover.prevent
@dragstart="handleDragStart(index)"
@drop="handleDrop(index)"
>
<div class="body_div">
<div class="bgc_circle" :style="{ 'background-color': item.bgc }">
<i>图标</i>
</div>
<div class="body_div_title">
{{ item.content }}
</div>
</div>
</div>
</div>
</div>
<div class="Finde_all">
<div class="Finde_collect_body">
<div class="Finde_collect_body_hover" @click="allState = !allState">
<!-- 向右箭头,下方不页面展示时显示 -->
<div v-if="!allState" class="arrow-right" />
<!-- 向下箭头,下方页面展示时 鼠标经过 显示 -->
<div v-if="allState" class="arrow-right_hover" />
<div class="collectBtn">全部应用</div>
</div>
<div style="color: #bdbdc3">
{{ items.length }}
</div>
</div>
<div v-if="allState">
<div
v-for="(item, index) in items"
:key="item.id"
:class="[{ 'gray-bg': item.isDragging }, 'block']"
draggable="true"
@dragend="handleDragEnd(index)"
@dragover.prevent
@dragstart="handleDragStart(index)"
@drop="handleDrop(index)"
>
<div class="body_div">
<ElTooltip
v-if="item.status === 0"
class="box-item"
placement="bottom"
>
<template #content> 收藏 </template>
<template #default>
<Icon
class="star"
icon="ic:twotone-star-border"
@click="handleCircleClick(index)"
/>
</template>
</ElTooltip>
<ElTooltip
v-if="item.status !== 0"
class="box-item"
effect="dark"
placement="bottom"
>
<template #content> 取消收藏 </template>
<template #default>
<Icon
class="star"
icon="material-symbols:star-rate-rounded"
@click="handleCircleClick(index)"
/>
</template>
</ElTooltip>
<div class="bgc_circle" :style="{ 'background-color': item.bgc }">
<i>图标</i>
</div>
<div class="body_div_title">
{{ item.content }}
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from "vue";
const collectState = ref(true);
const allState = ref(true);
const items = ref([
{
id: 1,
content: "会议室预约",
isDragging: false,
status: 0,
bgc: "#9c27b0",
},
{
id: 2,
content: "在线访问",
isDragging: false,
status: 0,
bgc: "#ff9800",
},
{
id: 3,
content: "快速访问",
isDragging: false,
status: 1,
bgc: "#2196f3",
},
{
id: 4,
content: "历史访问",
isDragging: false,
status: 0,
bgc: "#d48825",
},
]);
// 根据 status 分类
const collectItems = computed(() =>
items.value.filter((item) => item.status === 1)
);
let dragIndex = null;
const handleDragStart = (index) => {
dragIndex = index;
items.value[index].isDragging = true;
};
const handleDrop = (index) => {
const dragItem = items.value[dragIndex];
items.value.splice(dragIndex, 1);
items.value.splice(index, 0, dragItem);
};
const handleDragEnd = (index) => {
items.value.forEach((item) => {
item.isDragging = false;
});
console.log(items.value, "拖动结束时");
};
const handleCircleClick = (index) => {
if (items.value[index].status === 0) {
items.value[index].status = 1;
} else {
items.value[index].status = 0;
}
};
// 点击图标进行跳转
const handleRouterLink = ({ name }) => {
// 跳转
};
</script>
<style scoped lang="scss">
.FinderPage {
height: 80%;
padding: 30px 60px 0px 60px;
background-color: #ffffff;
.Finde_collect_body {
display: flex;
align-items: center;
margin-bottom: 10px;
.Finde_collect_body_hover {
padding-right: 10px;
margin-right: 5px;
height: 28px;
padding-left: 15px;
border-radius: 5px;
display: flex;
align-items: center;
.arrow-right_hover {
opacity: 0;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #9d9d9d;
}
}
.Finde_collect_body_hover:hover {
background-color: #f2f2f2;
.arrow-right_hover {
opacity: 1 !important;
}
}
.arrow-right {
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid #9d9d9d;
}
.collectBtn {
padding: 10px 0px;
padding-left: 8px;
font-size: 17px;
font-weight: bolder;
}
}
.block {
position: relative;
display: inline-block;
width: 150px;
height: 168px;
padding: 10px 0;
// background-color: white;
margin-right: 20px;
text-align: center;
vertical-align: middle;
// line-height: 100px;
cursor: move;
border-radius: 15px;
}
.star {
display: none;
position: absolute;
top: 10px;
left: 10px;
border: none;
}
.yellow {
color: yellow;
}
.block:hover {
background-color: #fafafa;
transform: translateY(-10px);
transition: all 0.3s;
.star {
display: block !important;
}
}
.body_div_title {
height: 100%;
}
.gray-bg {
//background-color: gray;
//margin-top: -2px;
}
.bgc_circle {
position: relative;
width: 80px;
height: 80px;
margin: 0 auto;
margin-bottom: 20px;
display: flex;
// background-color: rgb(156, 39, 176);
justify-content: center;
align-items: center;
border-radius: 50%;
cursor: pointer;
}
}
:deep(.el-tooltip__trigger:focus) {
outline: none; // 隐藏虚线边框
}
:deep(.el-tooltip__popper:focus, .el-tooltip__popper.is-focused) {
box-shadow: none; // 隐藏实线边框
}
</style>