Vue3.0利用vue-grid-layout插件实现拖拽布局

 

1、插件

首先,我们选择的插件是vue-grid-layout

npm i vue-grid-layout --save

官网:https://jbaysolutions.github....

 

2、插曲

安装完依赖,发现项目能启动起来,按照官网demo发现页面空白,控制台提示没有找到子组件

改变思路,不使用局部引入组件,使用全局引入组件。

 

3、实现

const layout = ref<LayoutItem[]>([
    { x: 0, y: 0, w: 1, h: 1, i: 0 },
    { x: 1, y: 0, w: 2, h: 1, i: 1 },
    { x: 0, y: 1, w: 2, h: 1, i: 2 },
    { x: 0, y: 2, w: 3, h: 1, i: 3 },
    { x: 2, y: 1, w: 1, h: 1, i: 4 },
  ]);

  <grid-layout
    :layout="layout"
    :col-num="3"
    :row-height="240"
    :is-draggable="true"
    :is-resizable="true"
    :is-mirrored="false"
    :maxRows="3"
    :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"
      @moved="onItemMoved"
    >{{ item.i }}</grid-item>
  </grid-layout>

效果:

但是!!
这里拖拽完没有判断每一行是否填充满且拖拽后有模块会被覆盖导致出现空白区域,如下:

思考:

我们需要增加校验,校验每一行是否填充满

 

4、校验函数

import { LayoutItem } from '../types/index';
import { cloneDeep } from 'lodash'
/**
* 校验布局是否合法
* 1.深拷贝数组,避免污染原数组
* 2.拿到y的最大值 用于遍历
* 3.拿到每个y的分数组 按照x升序排列
* 4.如果数组长度为1判断w是否等于最大x
* 5.如果数组长度不为1 遍历数组 判断每个元素的w是否等于下一个元素的x 累加w判断总和是否等于最大x
* 6.如果合法则返回false
* @param list 
* @returns 
*/
export const verifyLayout = (list: Array<LayoutItem>): boolean => {
  let yList = list.map(item => { return item.y });
  yList = yList.sort((a, b) => { return a - b });
  console.log(list);
  const newArr = cloneDeep(list);
  let flag = false;
  const maxY = yList[yList.length - 1];
  const maxX = 3;
  console.log(maxY);
  for (let i = 0; i <= maxY; i++) {
      let arr = newArr.filter((item: LayoutItem) => {
          return item.y === i;
      });
      console.log(arr, arr.length);
      if (arr && arr.length > 1) {
          console.log('多个个-------------------', i);
          let calValue = 0;
          arr = arr.sort((a: LayoutItem, b: LayoutItem) => { return a.x - b.x })
          arr.forEach((childItem: LayoutItem, index: number) => {
              calValue += childItem.w;
              console.log('calValue--------------', calValue, index);
              if (index !== arr.length - 1 && calValue !== arr[index + 1].x) {
                  flag = true;
              }
              if (index === arr.length - 1 && calValue !== maxX) {
                  flag = true;
              }
          })
      } else {
          console.log('只有一个-------------------', i);
          if (arr[0].w !== maxX) {
              flag = true
          }
      }
  }
  console.log(flag);
  return flag;
}

思路的话就是我在函数上的注释。
在每次拖拽完成的回调函数中进行校验

  /**
   * 拖拽完成事件
   * 1.将之前的数据存储到history数据中
   * 2.然后再将移动完成的数据存储到nowlayout数据中
   */
  const onItemMoved = () => {
    console.log('moved--------------------')
    historyDataList.value.push(cloneDeep(nowLayoutData.value));
    nowLayoutData.value = cloneDeep(layout.value);
    // const flag = verifyLayout(layout.value);
    // if (flag) {
    //   goBack()
    // }
  };
  const goBack = () => {
    console.log(historyDataList.value[historyDataList.value.length - 1]);
    layout.value = historyDataList.value[historyDataList.value.length - 1];
    nowLayoutData.value = cloneDeep(layout.value);
    historyDataList.value.pop();
  }


这样的话每次我们拖拽完校验如果不合法就会回滚,就能保证每一行填充满了!!!!

关于Vue3.0利用vue-grid-layout插件实现拖拽布局的文章就介绍至此,更多相关Vue3 利用vue-grid-layout插件实现拖拽布局内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 1、背景最近在面试找工作,然后面试官就问了有关自定义指令的问题,然后由于平时自定义指令用的不多,只是看过官方文档大概知道需要用到Vue.directive来自定义指令;面试结束之后,立刻就去网上找有关自定义 ...