vue实现portlet的效果
Vue 实现 Portlet 效果
Portlet 是一种模块化的用户界面组件,常用于门户网站中,允许用户自由拖拽、折叠或关闭各个模块。以下是基于 Vue 实现类似 Portlet 效果的几种方法:
使用第三方库实现拖拽布局
推荐使用 vue-grid-layout 或 vuedraggable 这类库快速实现可拖拽的 Portlet 布局。
<template>
<grid-layout
:layout.sync="layout"
:col-num="12"
:row-height="30"
:is-draggable="true"
:is-resizable="true"
>
<grid-item
v-for="item in layout"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:key="item.i"
>
<div class="portlet">
<div class="portlet-header">{{ item.title }}</div>
<div class="portlet-content">{{ item.content }}</div>
</div>
</grid-item>
</grid-layout>
</template>
<script>
import { GridLayout, GridItem } from "vue-grid-layout";
export default {
components: { GridLayout, GridItem },
data() {
return {
layout: [
{ x: 0, y: 0, w: 3, h: 4, i: "1", title: "模块1", content: "内容1" },
{ x: 3, y: 0, w: 3, h: 4, i: "2", title: "模块2", content: "内容2" },
],
};
},
};
</script>
<style>
.portlet {
border: 1px solid #ddd;
background: #fff;
}
.portlet-header {
padding: 8px;
background: #f5f5f5;
cursor: move;
}
.portlet-content {
padding: 8px;
}
</style>
自定义实现 Portlet 功能
若需完全自定义,可通过 Vue 的组件化特性结合事件监听实现基础功能:

<template>
<div class="portlet-container">
<div
v-for="(item, index) in portlets"
:key="index"
class="portlet"
@mousedown="startDrag(index, $event)"
>
<div class="portlet-header">
{{ item.title }}
<button @click="toggleCollapse(index)">折叠</button>
<button @click="removePortlet(index)">关闭</button>
</div>
<div class="portlet-content" v-show="!item.collapsed">
{{ item.content }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
portlets: [
{ title: "模块A", content: "内容A", collapsed: false },
{ title: "模块B", content: "内容B", collapsed: false },
],
draggingIndex: null,
startPos: { x: 0, y: 0 },
};
},
methods: {
startDrag(index, e) {
this.draggingIndex = index;
this.startPos = { x: e.clientX, y: e.clientY };
document.addEventListener("mousemove", this.handleDrag);
document.addEventListener("mouseup", this.stopDrag);
},
handleDrag(e) {
if (this.draggingIndex !== null) {
const dx = e.clientX - this.startPos.x;
const dy = e.clientY - this.startPos.y;
// 更新模块位置(需通过 CSS 或状态管理实现)
}
},
stopDrag() {
document.removeEventListener("mousemove", this.handleDrag);
document.removeEventListener("mouseup", this.stopDrag);
this.draggingIndex = null;
},
toggleCollapse(index) {
this.portlets[index].collapsed = !this.portlets[index].collapsed;
},
removePortlet(index) {
this.portlets.splice(index, 1);
},
},
};
</script>
<style>
.portlet-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.portlet {
border: 1px solid #ccc;
width: 200px;
user-select: none;
}
.portlet-header {
background: #eee;
padding: 8px;
display: flex;
justify-content: space-between;
}
</style>
关键功能扩展
- 持久化布局:通过
localStorage或后端 API 保存用户自定义的布局。 - 响应式设计:结合 CSS Grid/Flexbox 实现不同屏幕尺寸的适配。
- 动画效果:使用 Vue 的
<transition>为折叠/拖拽添加平滑动画。
以上方法可根据实际需求选择或组合使用。第三方库适合快速实现复杂交互,自定义方案则灵活性更高。






