所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

可视化布局编辑器必备!GridStack.js实现拖拽式页面构建器

还在为复杂的页面布局而头疼吗? GridStack.js 来拯救你!这是一个强大的拖拽网格布局库,让你的页面布局变得像搭积木一样简单!无论是仪表板、卡片布局还是响应式设计,GridStack.js 都能轻松搞定!

什么是 GridStack.js?

GridStack.js 是一个现代化的纯 TypeScript 库,专门用于创建可拖拽、可调整大小的响应式网格布局。它让你可以:

  • 拖拽元素:像移动桌面图标一样自由拖拽
  • 调整大小:随意调整元素尺寸
  • 响应式布局:自动适配不同屏幕尺寸
  • 灵活配置:支持各种自定义设置
  • 无依赖设计:纯原生 JavaScript,无需 jQuery

想象一下,你可以像在手机桌面上整理应用图标一样来设计你的网页布局!

核心特性

拖拽与调整大小

  • 直观拖拽:支持鼠标和触摸操作
  • 智能调整:元素可以自由调整大小
  • 碰撞检测:自动避免元素重叠
  • 网格吸附:元素自动对齐到网格

响应式设计

  • 多列布局:支持 1-12 列布局
  • 断点适配:不同屏幕尺寸自动调整
  • 移动端优化:完美支持触摸设备

高度可定制

  • 主题支持:多种内置主题
  • 动画效果:流畅的拖拽动画
  • 事件系统:丰富的事件回调
  • 嵌套网格:支持多层嵌套布局

️ 快速开始

安装

选择你喜欢的包管理器:

# 推荐使用 pnpm
pnpm add gridstack

# 或者使用 yarn
yarn add gridstack

# 或者使用 npm
npm install gridstack

基础使用

<template>
  <div class="grid-container">
    <div class="grid-stack" ref="gridStackRef"></div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { GridStack } from "gridstack";
import "gridstack/dist/gridstack.min.css";

const gridStackRef = ref(null);
let grid = null;

onMounted(() => {
  // 初始化网格
  grid = GridStack.init(
    {
      column: 12, // 列数
      cellHeight: 70, // 单元格高度
      margin: "6px", // 单元格间距
      removable: false, // 是否可删除
      acceptWidgets: true, // 是否可接受外部元素
      resizable: {
        handles: "se",
      },
    },
    gridStackRef.value
  );

  const initialData = [
    { x: 0, y: 0, w: 4, h: 2, content: "1" },
    { x: 4, y: 0, w: 4, h: 4, content: "2" },
    { x: 8, y: 0, w: 2, h: 2, content: "3" },
    { x: 10, y: 0, w: 2, h: 2, content: "4" },
    { x: 0, y: 2, w: 2, h: 2, content: "5" },
    { x: 2, y: 2, w: 2, h: 4, content: "6" },
    { x: 8, y: 2, w: 4, h: 2, content: "7" },
    { x: 0, y: 4, w: 2, h: 2, content: "8" },
    { x: 4, y: 4, w: 4, h: 2, content: "9" },
    { x: 8, y: 4, w: 2, h: 2, content: "10" },
    { x: 10, y: 4, w: 2, h: 2, content: "11" },
  ];
  grid.load(initialData);
});
</script>

<style>
.grid-container {
  width: 100%;
  background: #f5f5f5;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
  padding: 6px;
}
.grid-stack-item-content {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: white;
  border-radius: 8px;
  text-align: center;
}
</style>

常用配置属性

以下是 GridStack 常用的基础配置属性(GridStackOptions)说明:

属性名类型说明
cellHeightnumber/string每个网格单元的高度,支持像素(如 80)、百分比(如 ‘70%’)或 ‘auto’。
cellWidthnumber/string每个网格单元的宽度,通常自动计算,特殊场景可自定义。
columnnumber网格的列数,默认 12。
floatboolean是否启用浮动布局,true 时元素可自由排列。
resizableboolean/object是否允许调整大小,或传递详细配置对象(如 handles)。
draggableboolean/object是否允许拖拽,或传递详细配置对象(如 handle、cancel)。
marginnumber/string网格项之间的间距,支持像素或百分比。
minRownumber网格的最小行数。
maxRownumber网格的最大行数。
animateboolean拖拽/调整大小时是否启用动画。
removableboolean/string是否允许通过拖出网格删除元素,或指定删除区域的选择器。
acceptWidgetsboolean/string/function是否允许拖入外部元素,或指定选择器/函数。
disableResizeboolean是否全局禁用调整大小。
disableDragboolean是否全局禁用拖拽。

以下是 GridStackWidget(网格项)常用的基础属性说明:

属性名类型说明
xnumber网格项的起始列(从 0 开始计数)。
ynumber网格项的起始行(从 0 开始计数)。
wnumber网格项占据的列数(宽度)。
hnumber网格项占据的行数(高度)。
minWnumber网格项允许的最小列数。
maxWnumber网格项允许的最大列数。
minHnumber网格项允许的最小行数。
maxHnumber网格项允许的最大行数。
idstring/number网格项唯一标识(可选,便于后续查找和操作)。
lockedboolean是否锁定该网格项,锁定后无法拖拽和调整大小。
noResizeboolean是否禁止该网格项调整大小。
noMoveboolean是否禁止该网格项拖拽移动。
autoPositionboolean是否自动寻找空位插入该网格项(通常用于动态添加时)。
contentstring/HTMLElement网格项的内容(可选,实际开发中通常为插槽或自定义内容)。

进阶用法

content 渲染 html 标签

<template>
  <div class="grid-container">
    <div class="grid-stack" ref="gridStackRef"></div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { GridStack } from "gridstack";
import "gridstack/dist/gridstack.min.css";

const gridStackRef = ref(null);
let grid = null;

onMounted(() => {
  // 初始化网格
  grid = GridStack.init(
    {
      column: 12, // 列数
      cellHeight: 70, // 单元格高度
      margin: "6px", // 单元格间距
      removable: false, // 是否可删除
      acceptWidgets: true, // 是否可接受外部元素
      resizable: {
        handles: "se",
      },
    },
    gridStackRef.value
  );

  const initialData = [
    { x: 0, y: 0, w: 4, h: 2, content: "<strong>粗体文本</strong>" },
    { x: 4, y: 0, w: 4, h: 4, content: "<em>斜体文本</em>" },
    {
      x: 8,
      y: 0,
      w: 2,
      h: 2,
      content: "<span style='color: red;'>红色文本</span>",
    },
    {
      x: 10,
      y: 0,
      w: 2,
      h: 2,
      content:
        "<div style='background: yellow; padding: 5px;'>带背景的文本</div>",
    },
    { x: 0, y: 2, w: 2, h: 2, content: "5" },
    { x: 2, y: 2, w: 2, h: 4, content: "6" },
    { x: 8, y: 2, w: 4, h: 2, content: "7" },
    { x: 0, y: 4, w: 2, h: 2, content: "8" },
    { x: 4, y: 4, w: 4, h: 2, content: "9" },
    { x: 8, y: 4, w: 2, h: 2, content: "10" },
    { x: 10, y: 4, w: 2, h: 2, content: "11" },
  ];

  // 先加载数据,然后手动设置 HTML 内容
  grid.load(initialData);

  // 等待 DOM 更新后,手动设置每个项目的 HTML 内容
  setTimeout(() => {
    const gridItems = grid.getGridItems();
    initialData.forEach((item, index) => {
      if (gridItems[index]) {
        const contentEl = gridItems[index].querySelector(
          ".grid-stack-item-content"
        );
        if (contentEl) {
          contentEl.innerHTML = item.content || "";
        }
      }
    });
  }, 100);
});
</script>

<style>
.grid-container {
  width: 100%;
  background: #f5f5f5;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.1);
  padding: 6px;
}
.grid-stack-item-content {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: white;
  border-radius: 8px;
  text-align: center;
}
</style>

可调整大小/可拖动句柄

GridStack.init(
  {
    // 可调整大小
    resizable: {
      handles: "se,sw,ne,nw", // 拖拽方向 se-右下角,sw-左下角,ne-右上角,nw-左上角
    },
  },
  gridStackRef.value
);

禁用拖拽

GridStack.addWidget({
  x: 0,
  y: 0,
  w: 4,
  h: 2,
  content: "禁用拖拽",
  noMove: true,
});

禁用调整大小

GridStack.addWidget({
  x: 0,
  y: 0,
  w: 4,
  h: 2,
  content: "禁用调整大小",
  noResize: true,
});

锁定网格项

GridStack.addWidget({
  x: 0,
  y: 0,
  w: 4,
  h: 2,
  content: "锁定网格项",
  locked: true,
});

最佳实践

1. 性能优化

// 批量更新,避免频繁重绘
grid.batchUpdate();
grid.addWidget({ w: 2, h: 1, content: "元素1" });
grid.addWidget({ w: 2, h: 1, content: "元素2" });
grid.addWidget({ w: 2, h: 1, content: "元素3" });
grid.batchUpdate(false); // 结束批量更新

2. 内存管理

// 组件销毁时清理资源
onUnmounted(() => {
  if (grid) {
    grid.destroy();
    grid = null;
  }
});

3. 响应式设计

// 根据屏幕尺寸调整配置
const getGridConfig = () => {
  const width = window.innerWidth;
  return {
    column: width < 768 ? 4 : width < 1024 ? 8 : 12,
    cellHeight: width < 768 ? 60 : 80,
    margin: width < 768 ? 8 : 15,
  };
};

总结

GridStack.js 是一个功能强大、易于使用的网格布局库,特别适合:

  • 仪表板应用:数据可视化面板
  • 内容管理:拖拽式页面构建器
  • 响应式设计:多设备适配
  • 原型设计:快速布局验证

主要优势:

  • 零依赖:纯原生 JavaScript
  • 高性能:优化的渲染机制
  • 易上手:简单的 API 设计
  • 可扩展:丰富的配置选项
  • 跨平台:支持所有现代浏览器

现在就开始使用 GridStack.js,让你的页面布局变得像搭积木一样简单吧!


小贴士
GridStack.js 不仅支持 Vue 3,还支持 React、Angular 等主流框架。无论你使用什么技术栈,都能轻松集成!

相关链接

原文链接:https://code.ifrontend.net/archives/1371,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?