当前位置:首页 > VUE

vue实现portlet的效果

2026-02-24 06:59:17VUE

Vue 实现 Portlet 效果

Portlet 是一种模块化的用户界面组件,常用于门户网站中,允许用户自由拖拽、折叠或关闭各个模块。以下是使用 Vue 实现类似 Portlet 效果的几种方法:

使用 Vue Draggable 实现拖拽功能

安装 vuedraggable 库:

vue实现portlet的效果

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 库:

vue实现portlet的效果

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
分享给朋友:

相关文章

vue实现按钮刷新

vue实现按钮刷新

Vue 实现按钮刷新功能 在 Vue 中实现按钮刷新功能可以通过多种方式实现,具体取决于刷新需求是局部刷新还是全局刷新。以下是几种常见的方法: 使用 window.location.reload()…

vue查看更多怎么实现

vue查看更多怎么实现

实现 Vue 的“查看更多”功能 数据截取与显示控制 通过 v-if 或 v-show 控制内容的显示与隐藏。初始状态下只显示部分内容,点击“查看更多”后展开完整内容。 <template&g…

vue 实现tabs

vue 实现tabs

Vue 实现 Tabs 组件的方法 使用动态组件和 v-for 在 Vue 中实现 Tabs 可以通过动态组件和 v-for 指令结合完成。定义一个 tabs 数组,包含每个标签的标题和对应的组件。…

vue实现导出

vue实现导出

Vue 实现导出功能的方法 在 Vue 项目中实现导出功能通常涉及将数据导出为 Excel、CSV 或其他格式。以下是几种常见的实现方式: 使用 xlsx 库导出 Excel 安装 xlsx 库:…

vue 实现全屏

vue 实现全屏

Vue 实现全屏功能 在 Vue 中实现全屏功能可以通过浏览器提供的 Fullscreen API 完成。以下是一个完整的实现方案: 安装依赖(可选) 如果需要跨浏览器兼容性更好,可以安装…

vue实现portal

vue实现portal

Vue 实现 Portal 功能 Portal 是一种将子节点渲染到父组件 DOM 层级之外的 DOM 节点的技术,常用于实现模态框、弹出层等需要脱离当前组件层级的场景。Vue 可以通过多种方式实现…