vue实现portlet的效果
Vue 实现 Portlet 效果
Portlet 是一种模块化的用户界面组件,常用于门户网站中,允许用户自由拖拽、折叠或关闭各个模块。以下是使用 Vue 实现类似 Portlet 效果的几种方法:
使用 Vue Draggable 实现拖拽功能
安装 vuedraggable 库:
npm install vuedraggable
示例代码:
<template>
<draggable v-model="portlets" @end="onDragEnd">
<div v-for="portlet in portlets" :key="portlet.id" class="portlet">
<div class="portlet-header">
{{ portlet.title }}
<button @click="toggleCollapse(portlet.id)">折叠</button>
<button @click="removePortlet(portlet.id)">关闭</button>
</div>
<div class="portlet-body" v-show="!portlet.collapsed">
{{ portlet.content }}
</div>
</div>
</draggable>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: { draggable },
data() {
return {
portlets: [
{ id: 1, title: '模块1', content: '内容1', collapsed: false },
{ id: 2, title: '模块2', content: '内容2', collapsed: false }
]
};
},
methods: {
toggleCollapse(id) {
const portlet = this.portlets.find(p => p.id === id);
if (portlet) portlet.collapsed = !portlet.collapsed;
},
removePortlet(id) {
this.portlets = this.portlets.filter(p => p.id !== id);
},
onDragEnd() {
console.log('拖拽完成');
}
}
};
</script>
<style>
.portlet {
border: 1px solid #ddd;
margin-bottom: 10px;
}
.portlet-header {
background: #f5f5f5;
padding: 10px;
cursor: move;
}
.portlet-body {
padding: 10px;
}
</style>
使用 Grid Layout 实现响应式布局
安装 vue-grid-layout 库:
npm install vue-grid-layout
示例代码:
<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.i }}</div>
<div class="portlet-body">内容 {{ item.i }}</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' },
{ x: 3, y: 0, w: 3, h: 4, i: '2' }
]
};
}
};
</script>
自定义实现 Portlet 功能
如果需要更轻量级的实现,可以完全自定义 Portlet 组件:
<template>
<div class="portlet-container">
<div
v-for="portlet in portlets"
:key="portlet.id"
class="portlet"
:style="{ top: portlet.top + 'px', left: portlet.left + 'px' }"
@mousedown="startDrag(portlet.id, $event)"
>
<div class="portlet-header">
{{ portlet.title }}
<button @click="toggleCollapse(portlet.id)">折叠</button>
</div>
<div class="portlet-body" v-show="!portlet.collapsed">
{{ portlet.content }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
portlets: [
{ id: 1, title: '模块1', content: '内容1', collapsed: false, top: 0, left: 0 },
{ id: 2, title: '模块2', content: '内容2', collapsed: false, top: 0, left: 200 }
],
dragging: null,
offsetX: 0,
offsetY: 0
};
},
methods: {
startDrag(id, e) {
const portlet = this.portlets.find(p => p.id === id);
if (portlet) {
this.dragging = portlet;
this.offsetX = e.clientX - portlet.left;
this.offsetY = e.clientY - portlet.top;
document.addEventListener('mousemove', this.onDrag);
document.addEventListener('mouseup', this.stopDrag);
}
},
onDrag(e) {
if (this.dragging) {
this.dragging.left = e.clientX - this.offsetX;
this.dragging.top = e.clientY - this.offsetY;
}
},
stopDrag() {
this.dragging = null;
document.removeEventListener('mousemove', this.onDrag);
document.removeEventListener('mouseup', this.stopDrag);
},
toggleCollapse(id) {
const portlet = this.portlets.find(p => p.id === id);
if (portlet) portlet.collapsed = !portlet.collapsed;
}
}
};
</script>
<style>
.portlet-container {
position: relative;
height: 500px;
}
.portlet {
position: absolute;
width: 200px;
border: 1px solid #ddd;
background: white;
user-select: none;
}
.portlet-header {
padding: 10px;
background: #f5f5f5;
cursor: move;
}
.portlet-body {
padding: 10px;
}
</style>
以上方法提供了不同复杂度的实现方案,可以根据项目需求选择合适的方案。使用现成库可以快速实现功能,而自定义实现则更加灵活可控。







