Vue Grid Layout 拖拽改变元素位置和大小的一个好工具

官网

Vue Grid Layout 适用Vue.js的栅格布局系统

jbaysolutions.github.io/vue-grid-la...

中文官网

jbaysolutions.github.io/vue-grid-la...

github地址

github.com/jbaysolutio...

github地址releases下载

github.com/jbaysolutio...

简易上手

安装

css 复制代码
npm install vue-grid-layout --save

在组件中引入

javascript 复制代码
import { GridLayout, GridItem } from 'vue-grid-layout'

也可以在 index.html 文件中引入 js 文件

xml 复制代码
<script src="<%= BASE_URL %>static/javascript/vue-grid-layout.umd.js"></script>

然后在 main.js 入口文件中,引入。并且,全局注册。

javascript 复制代码
// 引入 vue-grid-layout 组件
import VueGridLayout from 'vue-grid-layout';

// 全局注册组件
Vue.component('grid-layout', VueGridLayout.GridLayout);
Vue.component('grid-item', VueGridLayout.GridItem);

基础用法

响应式布局 layout

css 复制代码
	new Vue({
	    el: '#app',
	    data: {
	        layout: [
                {"x":0,"y":0,"w":2,"h":2,"i":"0"},
                {"x":2,"y":0,"w":2,"h":4,"i":"1"},
                {"x":4,"y":0,"w":2,"h":5,"i":"2"},
                {"x":6,"y":0,"w":2,"h":3,"i":"3"},
                {"x":8,"y":0,"w":2,"h":3,"i":"4"},
                {"x":10,"y":0,"w":2,"h":3,"i":"5"},
                {"x":0,"y":5,"w":2,"h":5,"i":"6"},
                {"x":2,"y":5,"w":2,"h":5,"i":"7"},
                {"x":4,"y":5,"w":2,"h":5,"i":"8"},
                {"x":6,"y":3,"w":2,"h":4,"i":"9"},
                {"x":8,"y":4,"w":2,"h":4,"i":"10"},
                {"x":10,"y":4,"w":2,"h":4,"i":"11"},
                {"x":0,"y":10,"w":2,"h":5,"i":"12"},
                {"x":2,"y":10,"w":2,"h":5,"i":"13"},
                {"x":4,"y":8,"w":2,"h":4,"i":"14"},
                {"x":6,"y":8,"w":2,"h":4,"i":"15"},
                {"x":8,"y":10,"w":2,"h":5,"i":"16"},
                {"x":10,"y":4,"w":2,"h":2,"i":"17"},
                {"x":0,"y":9,"w":2,"h":3,"i":"18"},
                {"x":2,"y":6,"w":2,"h":2,"i":"19"}
            ],
	    },
	});
ruby 复制代码
<grid-layout
  :layout.sync="layout"
  :col-num="12"
  :row-height="30"
  :is-draggable="true"
  :is-resizable="true"
  :is-mirrored="false"
  :vertical-compact="true"
  :margin="[10, 10]"
  :use-css-transforms="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">
    {{item.i}}
    </grid-item>
</grid-layout>

属性说明

只说最基础,最常用的属性。其他的属性,可见官网传送门:

jbaysolutions.github.io/vue-grid-la...

GridLayout组件的属性:

layout

layout 是一个对象数组,

css 复制代码
 layout: [
 	{"x":0,"y":0,"w":2,"h":2,"i":"0"},
 	{"x":2,"y":0,"w":2,"h":4,"i":"1"}
 ]

每一条数据,必须 i, x, y, w 和 h 属性。在 GridItem 组件中,需要用到。

i 是元素的id唯一。

x是第几列。

y是第几行。

w是宽度,是 colWidth 的倍数。

h是高度,是 rowHeight 的倍数。

colNum

列数,默认为12

rowHeight

每一行的高度,单位是像素。

isDraggable

是否可拖拽。

isResizable

是否可调整大小。

除了属性,还有一些事件。事件,同样查看官网传送门:

jbaysolutions.github.io/vue-grid-la...

我只举一个例子,说明 resize 的用法。调整大小时的事件。

ini 复制代码
 @resize="resizeEvent"

当我调整某一个 GridItem 大小的时候,我希望相邻的 GridItem 的宽高,也发生改变。可以这么写:

ini 复制代码
    resizeEvent: function (i, newH, newW, newHPx, newWPx) {
      const currentItem = this.layout.find(item => item.i === i);
      const widthChange = newW - currentItem.w;
      const heightChange = newH - currentItem.h;
      currentItem.w = newW;
      currentItem.h = newH;
      this.handleWidthChange(currentItem, widthChange);
      this.handleHeightChange(currentItem, heightChange);
    },
    handleWidthChange: function (currentItem, widthChange, ids = []) {
      const rightNeighbors = this.layout.filter(item =>
        item.i !== currentItem.i &&
        item.y >= currentItem.y &&
        item.y < currentItem.y + currentItem.h &&
        item.x === currentItem.x + currentItem.w - widthChange
      );
      rightNeighbors.forEach(neighbor => {
        neighbor.x = currentItem.x + currentItem.w;
        let newWidth = neighbor.w - widthChange;
        newWidth = Math.max(1, newWidth);
        newWidth = Math.min(newWidth, this.numCols - neighbor.x);
        neighbor.w = newWidth;
        this.handleWidthChange(neighbor, widthChange);
      });
      const sameColumnBelowNeighbors = this.layout.filter(item =>
        !ids.includes(item.i) &&
        item.i !== currentItem.i &&
        item.x === currentItem.x &&
        item.y >= currentItem.y + currentItem.h
      );
      sameColumnBelowNeighbors.forEach(neighbor => {
        if (!ids.includes(neighbor.i)) {
          let newWidth = neighbor.w + widthChange;
          newWidth = Math.max(1, newWidth);
          newWidth = Math.min(newWidth, this.numCols - neighbor.x);
          neighbor.w = newWidth;
          ids.push(neighbor.i);
          this.handleWidthChange(neighbor, widthChange, ids);
        }
      });
    },
    handleHeightChange: function (currentItem, heightChange, ids = []) {
      const bottomNeighbors = this.layout.filter(item =>
        !ids.includes(item.i) &&
        item.i !== currentItem.i &&
        item.x >= currentItem.x &&
        item.x < currentItem.x + currentItem.w &&
        item.y === currentItem.y + currentItem.h - heightChange
      );
      bottomNeighbors.forEach(neighbor => {
        if (!ids.includes(neighbor.i)) {
          if (heightChange > 0) {
            neighbor.y = currentItem.y + currentItem.h;
            let newHeight = neighbor.h - heightChange;
            newHeight = Math.max(1, newHeight);
            newHeight = Math.min(newHeight, this.numRows - neighbor.y);
            neighbor.h = newHeight;
          } else {
            neighbor.y = currentItem.y + currentItem.h;
            let newHeight = neighbor.h - heightChange;
            newHeight = Math.max(1, newHeight);
            newHeight = Math.min(newHeight, this.numRows - neighbor.y);
            neighbor.h = newHeight;
          }
          ids.push(neighbor.i);
          this.handleHeightChange(neighbor, heightChange, ids);
        }
      });
      const sameRowRightNeighbors = this.layout.filter(item =>
        !ids.includes(item.i) &&
        item.i !== currentItem.i &&
        item.y === currentItem.y &&
        item.x > currentItem.x
      );
      sameRowRightNeighbors.forEach(neighbor => {
        if (!ids.includes(neighbor.i)) {
          let newHeight = neighbor.h;
          if (heightChange > 0) {
            if (currentItem.y + currentItem.h > neighbor.y + neighbor.h) {
              newHeight = neighbor.h + heightChange;
            }
          } else {
            if (currentItem.y + currentItem.h < neighbor.y + neighbor.h) {
              newHeight = Math.max(1, neighbor.h + heightChange);
            }
          }
          newHeight = Math.max(1, newHeight);
          newHeight = Math.min(newHeight, this.numRows - neighbor.y);
          neighbor.h = newHeight;
          ids.push(neighbor.i);
          this.handleHeightChange(neighbor, heightChange, ids);
        }
      });
    },

layout 数据是响应式,修改了相邻元素的属性,布局也随之发生改变。

扩展

官网,还有很多例子:

jbaysolutions.github.io/vue-grid-la...

如果,官网的属性,方法和例子,还不足以满足你的需求。

那么,可以去 github 下载 vue-grid-layout 的源码

按照自己的需求修改之后,重新打包

arduino 复制代码
npm run build-lib

在dist文件中生成

vue-grid-layout.umd.js

vue-grid-layout.umd.min.js

然后,在自己项目中引入即可。

比如说,想要 GridItem 支持重叠堆放,可以修改 helpers/utils.js 里面方法

compactmoveElement 这两个方法。

最后的话

以上,如果对你有用的话,不妨点赞收藏关注一下,谢谢 🙏

😊 微信公众号: OrzR3

💖 不定期更新一些技术类,生活类,读书类的文章。

相关推荐
予安灵8 分钟前
《白帽子讲 Web 安全:点击劫持》
前端·网络·安全·web安全·网络攻击模型·安全威胁分析·点击劫持
B站计算机毕业设计超人1 小时前
计算机毕业设计SpringBoot+Vue.js校园失物招领系统(源码+文档+PPT+讲解)
java·vue.js·spring boot·后端·毕业设计·课程设计·毕设
Enti7c2 小时前
什么是 jQuery
前端·javascript·jquery
计算机-秋大田2 小时前
基于SpringBoot的环保网站的设计与实现(源码+SQL脚本+LW+部署讲解等)
java·vue.js·spring boot·后端·课程设计
cafehaus2 小时前
关于JavaScript性能问题的误解
开发语言·javascript·ecmascript
taopi20242 小时前
若依vue plus环境搭建
前端·javascript·vue.js
李奶酪3 小时前
React Native 原理
javascript·react native·react.js
十八朵郁金香3 小时前
深入浅出理解编译器:前端视角
开发语言·前端·javascript
huangkaihao3 小时前
解锁Vue超能力:深度解析Render函数与高效渲染的奥秘
前端·vue.js·前端框架
桂月二二3 小时前
Island架构与部分水合技术解析:下一代Web应用的性能突围
前端·架构