当前位置:首页 > VUE

vue实现portlet的效果

2026-02-24 06:59:17VUE

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>

以上方法提供了不同复杂度的实现方案,可以根据项目需求选择合适的方案。使用现成库可以快速实现功能,而自定义实现则更加灵活可控。

vue实现portlet的效果

标签: 效果vue
分享给朋友:

相关文章

用vue实现搜索查询

用vue实现搜索查询

实现搜索查询的基本思路 在Vue中实现搜索查询功能通常涉及以下几个核心部分:数据绑定、事件监听、过滤逻辑和UI反馈。以下是一个完整的实现方案。 数据绑定与输入框 创建一个Vue组件,包含一个输入框…

vue实现批量

vue实现批量

Vue 实现批量操作的方法 在 Vue 中实现批量操作通常涉及选择多个项目并执行统一处理,例如批量删除、批量更新等。以下是几种常见实现方式: 表格多选批量操作 使用 el-table 配合复选框实…

vue实现粘贴

vue实现粘贴

Vue 实现粘贴功能的方法 在 Vue 中实现粘贴功能通常涉及监听粘贴事件并处理剪贴板数据。以下是几种常见的实现方式: 监听原生粘贴事件 通过 @paste 指令或原生 addEventListe…

vue diff实现

vue diff实现

Vue Diff 算法实现原理 Vue 的虚拟 DOM Diff 算法(即 patch 过程)是其高效渲染的核心,主要通过对比新旧虚拟节点的差异,最小化 DOM 操作。以下是关键实现要点: 同层级比…

vue实现接口

vue实现接口

在 Vue 中实现接口请求 Vue 本身不直接提供 HTTP 请求功能,通常需要借助第三方库如 axios 或 fetch 来实现接口请求。以下是几种常见方法: 使用 axios 发送请求 安装 a…

vue实现dag

vue实现dag

Vue实现DAG(有向无环图) 在Vue中实现DAG(Directed Acyclic Graph,有向无环图)通常涉及数据结构的建模、可视化渲染以及交互逻辑处理。以下是关键实现步骤和示例代码: 数…