Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

这篇具有很好参考价值的文章主要介绍了Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

官网:Vue Grid Layout -️ 适用Vue.js的栅格布局系统

Gitee:https://gitee.com/wfeng0/vue2-grid-layout 

一、 Vue Grid Layout 简介 

在官网的描述中,我们可以看出,该栅格布局具有以下特性:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 在具有拖拽组成页面、组件动态调整大小、边缘碰撞监测的系统中,使用该布局无疑是最合适的。当然,目前也有很多现成的文章、博客,今天主要按照官网的学习思路,讲解一下该栅格系统的基本使用。

该栅格系统目前对 vue2 的支持是最好的,vue3 是需要用插件支持的,会在小节详细讲解。

二、vue-grid-layout 的安装与使用

// 安装:
npm install vue-grid-layout --save

// 引用:
import { GridLayout, GridItem } from 'vue-grid-layout'

// 注册:
components:{ GridLayout, GridItem }

完成上诉步骤之后,复制官网的《用法》一节代码到项目中:

data() {
        return {
            // 定义栅格系统数据源
            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" }
            ],

        }
    },
 <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>

得到如下图,即表示该栅格系统已经能正常使用了,下面慢慢介绍其属性与事件方法。

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

  给 gridItem(是item) 添加样式:

 <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" class="gridItem">
            {{ item.i }}
        </grid-item>

// 对应的less
<style lang="less" scoped>
.gridItem {
    border: solid black 1px;
    background-color: #CCCCCC;
}
</style>

这样子,是不是就很像官网的例子了 

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 三、 属性

简单说一下经常用到的属性,所有的属性可以前往官网查看描述,我们先来了解一下gridItem的必要属性吧,它对我们的讲解是非常重要的。

3.1 gridItem 的必须属性

这是gridItem的数据项:{ "x": 0, "y": 0, "w": 2, "h": 2, "i": "0" },包含x、y、w、h、i。

    *   1. i:  栅格中元素的ID

    *   2. x: 标识栅格元素位于第几列

    *   3. y: 标识栅格元素位于第几行

    *   4. w: 标识栅格元素的初始宽度(值为colWidth的倍数)

    *   5. h: 标识栅格元素的初始高度(值为rowHeight的倍数)

 理解基本概念后,详细说说参数含义(只取第一个数据项:{ "x": 0, "y": 0, "w": 2, "h": 2, "i": "0" }): Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

将X设为5:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 将Y设为3:【目前无法设置为3,因为item会一直处于第一行,稍后再处理,因为现在还不能处于随意位置】

 而W、H就相对简单了,控制数据项的宽度、高度: 

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

    *   6. minW:栅格元素的最小宽度(值为colWidth的倍数)

    *   7. minH:栅格元素的最小高度(值为rowHeight的倍数)

    *   8. maxW:栅格元素的最大宽度(值为colWidth的倍数)

    *   9. maxH:栅格元素的最大高度(值为rowHeight的倍数)

了解了基本属性后,我们可以看GridLayout的属性了,因为item的其他属性会继承父级属性,在看其元素前,我们需要知道框架的元素计算方法。

3.2 背景框实现

【0721新增章节】大家对这个背景框是怎么实现的还是模模糊糊,可能下面的代码还是太简洁了,也很多人问,特地再开个章节,专门讲一下背景框是如何实现的。

<grid-layout>
    // grid-layout 允许有多个 grid-item,可以用于预览、碰撞检测、背景框等多用途;
    // 本质上也是一个 拖拽画布,只是 不可缩放,不可拖拽,底层是由 layout 数据渲染而成
    <grid-item> // 拖拽背景</grid-item> 
    <grid-item> // 实际数据</grid-item>
</grid-layout>

官网的样例: 

<template>
  <div>
    <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>
  </div>
</template>

<script>
import VueGridLayout from "vue-grid-layout";
export default {
  components: {
    gridLayout: VueGridLayout.GridLayout,
    gridItem: VueGridLayout.GridItem,
  },

  data() {
    return {
      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" },
      ],
    };
  },
};
</script>

<style lang="less" scoped></style>

上面这个代码应该都看得懂吧,最最最基础的 gridlayout 官网样例,给grid-item 添加样式:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 然后,我们现在重新设计数据项,每一个数据项只能占1格

  <grid-item
        v-for="item in backLayout" // 改为渲染背景框
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        :key="item.i"
        class="gridItem"
      >
        {{ item.i }}
      </grid-item>
 
backLayout: [
        { x: 0, y: 0, w: 1, h: 1, i: "0" },
        { x: 1, y: 0, w: 1, h: 1, i: "1" },
        { x: 2, y: 0, w: 1, h: 1, i: "2" },
        { x: 3, y: 0, w: 1, h: 1, i: "3" },
        { x: 4, y: 0, w: 1, h: 1, i: "4" },

        { x: 0, y: 1, w: 1, h: 1, i: "10" },
        { x: 1, y: 1, w: 1, h: 1, i: "11" },
        { x: 2, y: 1, w: 1, h: 1, i: "12" },
        { x: 3, y: 1, w: 1, h: 1, i: "13" },
        { x: 4, y: 1, w: 1, h: 1, i: "14" },

        { x: 0, y: 2, w: 1, h: 1, i: "20" },
        { x: 1, y: 2, w: 1, h: 1, i: "21" },
        { x: 2, y: 2, w: 1, h: 1, i: "22" },
        { x: 3, y: 2, w: 1, h: 1, i: "23" },
        { x: 4, y: 2, w: 1, h: 1, i: "24" },

        { x: 0, y: 3, w: 1, h: 1, i: "30" },
        { x: 1, y: 3, w: 1, h: 1, i: "31" },
        { x: 2, y: 3, w: 1, h: 1, i: "32" },
        { x: 3, y: 3, w: 1, h: 1, i: "33" },
        { x: 4, y: 3, w: 1, h: 1, i: "34" },
      ],

就得到每一个框的位置,都有一个元素了 

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 添加背景,实现虚线:

.box {
  background-color: #031e2c;
  height: 100vh;
}
.gridItem {
  color: #fff;
  border: dashed #ccc 1px;
}

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 到这里应该也没有看不懂的吧,然后就什么都不要操作了,你只需要确保每一个位置上有一个元素,w 1 h 1 就够了,设置背景框不可缩放、不可拖拽::is-draggable="false" :is-resizable="false",是放在 grid-item backLayout 上,不然整个都不可以缩放、拖拽了!!同时,确保背景在第一个位置上,因为先渲染的,会在最底层:

  <grid-layout
      :layout.sync="layout" // 这个同步的是真正的layout数据
      :col-num="5"
      :row-height="150"
      :is-draggable="true"
      :is-resizable="true"
      :is-mirrored="false"
      :vertical-compact="true"
      :margin="[10, 10]"
      :use-css-transforms="true"
    >
      <!-- 确保在其他 item 下面,放在第一个的会在最下面 -->
      <grid-item 
        v-for="item in backLayout" // 这个是背景框的数据
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        :key="item.i"
        :is-draggable="false"
        :is-resizable="false"
        class="backGridItem"
      >
      </grid-item>

      <!-- 真正的layout数据 -->
      <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"
        :is-draggable="true" // 可以拖拽,为 true,可以不设置,默认随 grid-layout
        :is-resizable="true" // 可以缩放,为 true,可以不设置,默认随 grid-layout
        class="gridItem" // 以不同颜色区分
      >
      </grid-item>
    </grid-layout>


 layout: [{ x: 0, y: 0, w: 1, h: 1, i: "0" }],

就变成这样了: 

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 这样便实现了背景框。完整的代码我放到附录里了,我就不上传 git了。还有不懂的,在给我私信留言,给你VIP一对一讲解哈哈哈哈

3.3 框架元素的实际宽度高度计算方式

        已知colNum是定义列数,rowHeight是指每一行的高度(这个的单位是 px); 如上图,将父盒子拆分为三行、五列,我放一个格子元素,实际占比是下图:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 元素的实际高宽,等于一个格子的尺寸,问:占2×2个格子数的元素尺寸呢?

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

用代码验证一下:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

就是需要理解margin的存在即可。 因此可以得出结论

// 元素的尺寸计算方法
宽度 width = ( box / colNum ) * w + ( w - 1 ) * margin + border
高度 height= rowHeight * h +( h - 1 ) * margin + border

我们用代码验证一下这个格子数:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 这样更清晰看到,缩放后,元素的尺寸确实是包含margin值的。

元素的宽高与实际的w、h值,是存在一个加上(n-1)的margin值的关系, 花了很大篇幅说明了这个框架的宽高计算方式,一定记得是(n-1)的关系,在页面上计算元素尺寸时,别忘了margin的存在!

3.4 元素尺寸的计算方法总结

【3月17日 新增章节:元素尺寸的计算方法】

我看很多人的评论,还是对这个元素的尺寸计算有疑问,我现在再对这个难点讲解一下:

        1. 我们的拖拽区 width: 1500px; height:650px;将其宽度分成10份,每一份多宽?(占多少px)

        我们知道,配置时,我们设定了 margin:[10,10],因此,每一个元素,都应具有上下左右的边距。因此,得出下图:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 2. :row-height="50" 这个属性表示每一行的高度是 50px,那么,650px的高度,可以分成多少行?

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 这里也是有 n+1 的间距,解不等式,就可得到 最大是10。

我们总结一下计算公式:

宽度:设共可分为 n 列,那么, width - (n+1)*margin / n = 每个元素的实际宽度

高度:设共可分为 m 行,那么,row-height * m + (m + 1) * margin <= height

因此,元素的宽高,可以根据实际的拖拽区的宽高,动态计算出来

不知道这么解释,能不能理解?如果还是有些模糊,可以看看我的下一篇项目实践,或者给我留言。

3.5 gridLayout 的属性

    *  1. layout:栅格布局的数据源,数据源为数组Array,数据项为对象,必须包含 i, x, y, w 和 h 属性.

     *  2. colNum:定义栅格系统的列数

     *  3. rowHeight:每行的高度,单位像素

     *  4. maxRows:定义最大行数

     *  5. isDraggable:标识栅格中的元素是否可拖拽

     *  6. isResizable:标识栅格中的元素是否可调整大小

     *  7. preventCollision:防止碰撞属性,值设置为ture时,栅格只能拖动至空白处

(我们将数据项宽度高度设为1,便于查看效果)

colNum:是定义列数

 rowHeight:是指每一行的高度(这个的单位是 px)

 margin:定义栅格中的元素边距(数组中第一个元素表示水平边距,第二个表示垂直边距,单位为像素)

其他属性就比较简单了,不再大篇幅介绍了,后面遇到了我们再细说。主要大家一定要了解计算规则,这个框架就非常容易掌握了,遇到BUG,基本上是margin的问题。

四、事件

官网描述:事件 | Vue Grid Layout -️ 适用Vue.js的栅格布局系统

这章节官网已经描述得非常好了,也有demo、样例,我就不细说了。

五、vue-grid-layout 的实际应用

5.1 移动到任意位置

上诉还遗留一个问题没处理,就是元素不能移动到任意位置

gridLayout  verticalCompact 属性: 标识布局是否垂直压缩,为false时,垂直方向不压缩,可以放置元素。

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 5.2  移动事件与调整大小

事件分两组,事件执行中和事件执行完毕。

移动事件有三个参数:i、newX、newY,i标识唯一移动元素ID和新的位置

         @move="moveEvent"

        @moved="movedEvent"

调整大小事件有5个参数:i、newH、newW及h、w的px(像素)单位

        @resize="resizeEvent"

        @resized="resizedEvent"

常用的事件就是这两组,我们也会详细说明及应用。

5.3 实现两个元素的交换

元素的交换是最简单的应用,当元素覆盖到一个元素上时,交换两者的位置。类似交换两个数,一定需要第三个变量,我们使用深拷贝的方式实现数据缓存。

mounted() {
    this.map = JSON.parse(JSON.stringify(this.layout));
  },

实现思路:移动中,判断位置上是否有元素,有的话,交换两者数据即可。

moveEvent(i, x, y) {
      console.log("移动中--move", i, x, y);
      //   1 根据移动位置,循环数据源当前位置是否有元素,不包含自己的位置
      const finditem = this.map.find(
        (item) => item.x === x && item.y === y && item.i != i
      );
      if (!finditem) return;
      console.log("找到了", finditem);
      this.changePosition(
        this.layout.find((item) => item.i === i),
        finditem
      );
    },

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 逻辑理清后,开始交换了:

// 交换位置:
    changePosition(item1, item2) {
      console.log(item1, item2);
      // 定义中间变量交换
      const temp = this.deepClone(item1);
      //   注意:修改的是影响显示的实际数组 layout
      this.layout.forEach((item) => {
        // 找到 item1,将 item1 的信息换成item2
        if (item.i === item1.i) {
          item.x = item2.x;
          item.y = item2.y;
        }
        if (item.i === item2.i) {
          item.x = temp.x;
          item.y = temp.y;
        }
      });
      // 实现交换后,及时同步 数据映射
      this.map = this.deepClone(this.layout);
    },

但是这样还有一个小问题,我希望是两个原始位置交换,而不是移动过程中的最新位置,这就需要获取数据映射中的原始数据:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

实现效果: 

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

简单实现到这就行了,当然还有其他的问题,比如相同尺寸的才能交换、多换少、匹配后非立马交换等问题,还是影响用户体验的,我们将这些问题留后面处理。

5.4 指定允许拖动的元素

这个场景比较常见,在实际项目中,不可能整体结构允许拖动,因为要涉及结构的事件响应等,因此,为其设计允许拖动的元素就比较重要了。

【GridItem 属性】

# dragIgnoreFrom(标识栅格元素中哪些子元素无法触发拖拽事件,值为css-like选择器)

# dragAllowFrom (标识栅格元素中哪些子元素可以触发拖拽事件,值为css-like选择器)

<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"
        @move="moveEvent"
        @moved="movedEvent"
        @resize="resizeEvent"
        @resized="resizedEvent"
        class="gridItem"
        :style="{ backgroundColor: item.i === '0' ? '' : 'pink' }"
        drag-ignore-from=".gridBox"
        drag-allow-from=".draggable"
      >
        <div class="gridBox">不允许拖动</div>
        <div class="draggable"></div>
      </grid-item>
.gridItem {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    border: solid #fff 1px;
    background-color: #cccccc;

    .draggable {
      position: absolute;
      left: 0;
      top: 0;
      width: 10px;
      height: 10px;
      background-color: #000;
      border-radius: 10px;
      cursor: pointer;
    }
  }

只有指定元素才能拖动,其他未指定的均不允许拖动:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 5.5 动态添加/删除元素

动态添加元素就是往数组对象中 push 新的item数据项:

 add() {
      this.layout.push({
        x: 1,
        y: 2, // puts it at the bottom
        w: 1,
        h: 1,
        i: this.layout.length + 1,
      });
    },

 而删除元素,就是获取元素的i,执行 this.layout.splice(index, 1) 操作。

dele(i) {
      this.layout.splice(
        this.layout.findIndex((item) => item.i === i),
        1
      );
    },

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

5.6 外部添加元素

原理就是利用事件源,将外部元素拖动到布局内,动态计算其位置,动态添加元素。

为了计算方便,我们将布局系统放置 top:0,left:0的位置

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)这里就需要计算我们的格子数、格子宽高。

5.6.1 拖拽到布局内,会得到实时坐标

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 事件源中,有  x: 334 y: 161,两个属性.

5.6.2 动态计算释放后,该在什么位置

我们用draged事件监听,移动中事件触发太多次了(事件源是一样的,均有 x、y属性)。

当前坐标 336 299,我们如何确定位于那个格子中(需要格子尺寸做计算)?

按照我们上的计算方法:

// 元素的尺寸计算方法
宽度 width = ( box / colNum ) * w + ( w - 1 ) * margin + border
高度 height= rowHeight * h +( h - 1 ) * margin + border

格子尺寸:  ( box / colNum )* rowHeight,我就不算了,直接获取:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

因此,每一个格子尺寸是 270*102,当前坐标 336 299,计算位置【位置指的是在栅格系统中的x、y】:

需要处理 margin ,我们将其归为格子的尺寸,因此,计算时,格子是180*112

336/280=1.2

299/112=2.6

我们向上取整:应该在第三行、第二列。

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 能获取到坐标后动态push元素:

 // 动态添加元素
      this.layout.push({
        x: gx - 1,
        y: gy - 1,
        w: 1,
        h: 1,
        i: `item(x:${ex},y:${ey})`,
      });

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 5.7 动态拖拽预览

上面实现太生硬了,我们拖进去,不知道其具体位置,我们做一个预览功能.(新的grid-item)

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

拖动到某一个格子时,能实时展现预览位置能更好。新建 grid-item,使用 previewData:[]空数组做数据源,拖拽事件执行过程中,动态添加preview的数据,实时更新预览数据,这样的交互是最好的:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

六、 Vue3 的使用

【vue3章节讲解太简单了,今天补充一下吧】

// 下载 vue-grid-layout
npm install vue-grid-layout --save

// 下载 vue3 插件支持
npm install vue-grid-layout@3.0.0-beta1 --save

// main.js中注册
import gridLayout from 'vue-grid-layout'

createApp(App).use(gridLayout).mount('#app')

// 在main.js注册后,不需要在 import 引入,直接使用(App.vue)

<template>
  <grid-layout
    :layout="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>
</template>

<script setup>
import { reactive } from "vue";

// 使用 vue3 setup 语法糖
const layout = reactive([
  { 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" },
]);
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
</style>

添加样式:

.grid-item {
  display: flex;
  align-items: center;
  justify-content: center;
  border: solid #ccc 1px;
  background-color: #ccc;
}

得到如下:

Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)

 那剩下的就是事件啥的了,跟vue2 是一样的。主要是能在vue3中出现这个图,表示已经没问题了。

 总结

栅格布局难度不大,但是要理解里面的原理,并实际应用到自己的项目开发,还要结合自己项目的实际情况。里面涉及的逻辑主要是计算宽高、拖拽事件处理等多角度问题,想要实现更加丰富的功能,主要是能使用多个 item 系统,实现堆叠效果。优化部分留给大家思考了,有问题欢迎交流讨论。别忘了推荐些gif工具哈~文章来源地址https://www.toymoban.com/news/detail-415303.html

附录一:背景框的完整代码

<template>
  <div class="box">
    <grid-layout
      :layout.sync="layout"
      :col-num="5"
      :row-height="150"
      :is-draggable="true"
      :is-resizable="true"
      :is-mirrored="false"
      :vertical-compact="true"
      :margin="[10, 10]"
      :use-css-transforms="true"
    >
      <!-- 确保在其他 item 下面,放在第一个的会在最下面 -->
      <grid-item
        v-for="item in backLayout"
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        :key="item.i"
        :is-draggable="false"
        :is-resizable="false"
        class="backGridItem"
      >
      </grid-item>

      <!-- 真正的layout数据 -->
      <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"
        class="gridItem"
      >
      </grid-item>
    </grid-layout>
  </div>
</template>

<script>
import VueGridLayout from "vue-grid-layout";
export default {
  components: {
    gridLayout: VueGridLayout.GridLayout,
    gridItem: VueGridLayout.GridItem,
  },

  data() {
    return {
      layout: [{ x: 0, y: 0, w: 1, h: 1, i: "0" }],
      backLayout: [
        { x: 0, y: 0, w: 1, h: 1, i: "0" },
        { x: 1, y: 0, w: 1, h: 1, i: "1" },
        { x: 2, y: 0, w: 1, h: 1, i: "2" },
        { x: 3, y: 0, w: 1, h: 1, i: "3" },
        { x: 4, y: 0, w: 1, h: 1, i: "4" },

        { x: 0, y: 1, w: 1, h: 1, i: "10" },
        { x: 1, y: 1, w: 1, h: 1, i: "11" },
        { x: 2, y: 1, w: 1, h: 1, i: "12" },
        { x: 3, y: 1, w: 1, h: 1, i: "13" },
        { x: 4, y: 1, w: 1, h: 1, i: "14" },

        { x: 0, y: 2, w: 1, h: 1, i: "20" },
        { x: 1, y: 2, w: 1, h: 1, i: "21" },
        { x: 2, y: 2, w: 1, h: 1, i: "22" },
        { x: 3, y: 2, w: 1, h: 1, i: "23" },
        { x: 4, y: 2, w: 1, h: 1, i: "24" },

        { x: 0, y: 3, w: 1, h: 1, i: "30" },
        { x: 1, y: 3, w: 1, h: 1, i: "31" },
        { x: 2, y: 3, w: 1, h: 1, i: "32" },
        { x: 3, y: 3, w: 1, h: 1, i: "33" },
        { x: 4, y: 3, w: 1, h: 1, i: "34" },
      ],
    };
  },
};
</script>
<style>
* {
  margin: 0;
  padding: 0;
}
</style>

<style lang="less" scoped>
.box {
  background-color: #031e2c;
  height: 100vh;
}
.backGridItem {
  color: #fff;
  border: dashed #ccc 1px;
}
.gridItem {
  background-color: green;
}
</style>

到了这里,关于Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue中如何使用 ECharts 提供的多种布局方式,如 grid、grid3D、geo 等

    ECharts提供的多种布局方式 ECharts提供的多种布局方式举例 vue中如何使用ECharts提供的多种布局方式 ECharts提供的多种布局方式,如grid、grid3D和geo,用于控制图表元素在坐标系中的位置和布局。下面是对每种布局方式的简要解释: grid布局:grid布局方式用于将图表元素放置在一

    2024年02月21日
    浏览(38)
  • 记录--Vue3基于Grid布局简单实现一个瀑布流组件

    在学习Grid布局之时,我发现其是CSS中的一种强大的布局方案,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,在刷某书和某宝首页时,我们发现其展示方式就是一种瀑布流,是一种流行的网站页面布局,视觉表现为参差不齐的多栏布局,随着页

    2024年02月05日
    浏览(66)
  • css3-grid:grid 布局 / 基础使用

    一、理解 grid   二、理解 css grid 布局 CSS Grid布局是一个二维的布局系统,它允许我们通过定义网格和网格中每个元素的位置和尺寸来进行页面布局。CSS Grid是一个非常强大的布局系统,它不仅可以用于构建网格布局,还可以用于定位元素,并且可以很好地处理复杂的布局。

    2024年02月12日
    浏览(42)
  • vue AntD中栅格布局的四种大小xs,sm,md,lg

    cssBootstrap栅格布局的四种大小xs,sm,md,lg 前端为了页面在不同大小的设备上也能够正常显示,通常会使用栅格布局的方式来实现。 使用bootStrap的网格系统时,常见到一下格式的类名 col-*-* visible-*-* hidden_*_* 中间可为xs,xsm,md,lg等表示大小的单词的缩写 右边为1-12之内、用于元素所

    2024年02月04日
    浏览(33)
  • HarmonyOS4.0系统性深入开发34栅格布局(GridRow/GridCol)

    栅格布局是一种通用的辅助定位工具,对移动设备的界面设计有较好的借鉴作用。主要优势包括: 提供可循的规律:栅格布局可以为布局提供规律性的结构,解决多尺寸多设备的动态布局问题。通过将页面划分为等宽的列数和行数,可以方便地对页面元素进行定位和排版。

    2024年02月21日
    浏览(51)
  • 使用Vue.js框架的指令和事件绑定实现一个购物车的页面布局

    使用了v-model指令来实现全选/全不选的功能,当全选框被点击时,isAllChecked的值会被改变。 使用了v-if指令来判断购物车中是否有商品,如果有商品则渲染商品列表,否则显示购物车为空的提示。 使用了v-for指令来遍历datalist数组,渲染每个商品项。 使用了@change事件来监听商

    2024年02月12日
    浏览(55)
  • 鸿蒙开发-UI-布局-栅格布局

    鸿蒙开发-UI-布局 鸿蒙开发-UI-布局-线性布局 鸿蒙开发-UI-布局-层叠布局 鸿蒙开发-UI-布局-弹性布局 鸿蒙开发-UI-布局-相对布局 文章目录 前言 一、基本概念 二、格栅容器组件 1.栅格系统断点 2.布局的总列数 3.排列方向 4.子组件间距 三、格栅容器子组件 1.span 2.offset 3.order 四、

    2024年02月20日
    浏览(39)
  • 弹性盒子布局 Flexbox Layout

    可以嵌套下去 1.display 属性 默认行排列 此时是 列拍 flex-direction属性——行布局 row 列布局:column flex-wrap 属性 折叠 flex-flow属性 包括 flex-direction 和flex-wrap flex-flow: row wrap 行排列 折叠 justify-content属性 元素在主轴上的对齐方式 左对齐 居中对齐 右对齐 两端对齐 拉手对齐 align

    2024年03月15日
    浏览(47)
  • Qt入门教程【Core篇】Layout布局(布局管理器、手动布局)

    😈 「CSDN主页」 :传送门 😈 「Bilibil首页」 :传送门 😈 「网易云课堂」 :传送门 😈 「CSDN学院」 :传送门 😈 「51CTO学院」 :传送门 😈 「本文的内容」 :Qt布局指南 😈 「动动你的小手」 : 点赞 👍 收藏 ⭐️ 评论 📝 界面开发首先要对整个界面进行布局,使窗体上

    2023年04月18日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包