乐趣区

关于vue.js:Vue30基于vuegridlayout插件实现拖拽布局

最近遇到个需要须要对页面布局进行拖拽而后扭转布局,保留布局

插件

首先,咱们抉择的插件是 vue-grid-layout

npm i vue-grid-layout --save

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

插曲

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

扭转思路,不应用部分引入组件,应用全局引入组件。

实现

 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>

成果:

然而!!
这里拖拽完没有判断每一行是否填充斥且拖拽后有模块会被笼罩导致呈现空白区域,如下:

思考

咱们须要减少校验,校验每一行是否填充斥
1. 校验函数

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();}

这样的话每次咱们拖拽完校验如果不非法就会回滚,就能保障每一行填充斥了!!!!

退出移动版