拖拽宮格vue-grid-layout的使用及案例

1、前言

vue-grid-layout是一個適用于vue的拖拽柵格布局庫,功能齊全,適用于拖拽+高度/寬度自由調(diào)節(jié)的布局需求。本文將講述一些常用參數(shù)和事件,以及做一個同步拖拽的Demo。效果動態(tài)圖如下:


grid-layout.gif

2、安裝

  • vue2版本:
npm install vue-grid-layout --save
  • vue3版本:
npm install vue-grid-layout@3.0.0-beta1 --save

3、屬性

  • GridLayout 容器:
屬性名 類型 必填 默認值 描述
layout Array<Object> - 數(shù)據(jù)源,每一項必須有i, x, y, w 和 h屬性
colNum Int 12 列數(shù)
rowHeight Int 150 每行的高度像素
maxRows Int Infinity 最大行數(shù)
margin Array<number> [10, 10] 元素邊距
isDraggable Boolean true 是否可拖拽
isResizable Boolean true 是否可調(diào)整大小
isMirrored Boolean false 是否可鏡像反轉(zhuǎn)
autoSize Boolean true 是否自動調(diào)整大小
verticalCompact Boolean true 布局是否垂直壓縮
preventCollision Boolean false 防止碰撞,為true則元素只能拖動至空白處
useCssTransforms Boolean true 是否使用CSS屬性 transition-property: transform
responsive Boolean false 布局是否為響應(yīng)式
breakpoints Boolean { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 } 為響應(yīng)式布局設(shè)置斷點
cols Boolean { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 } 設(shè)置每個斷點對應(yīng)的列數(shù)
  • GridItem 子項:
屬性名 類型 必填 默認值 描述
i string - 子項ID
x number - 元素位于第幾列
y number - 元素位于第幾行
w number - 初始寬度,值必須為colNum的倍數(shù)
h number - 初始高度,值必須為rowHeight的倍數(shù)
minW number 1 元素最小寬度,值必須為colNum的倍數(shù),如果w小于minW,則minW的值會被w覆蓋
minH number 1 元素最小高度,值必須為rowHeight的倍數(shù),如果h小于minH,則minH的值會被h覆蓋
maxW number Infinity 元素最大寬度,值必須為colNum的倍數(shù),如果w大于maxW,則maxW的值會被w覆蓋
maxH number Infinity 元素最大高度,值必須為rowHeight的倍數(shù),如果h大于maxH,則maxH的值會被h覆蓋
isDraggable Boolean null 是否可拖拽。如果值為null則取決于父容器
isResizable Boolean null 是否可調(diào)整大小。如果值為null則取決于父容器
static Boolean false 是否為靜態(tài)的,無法拖拽、調(diào)整大小或被其他元素移動
dragIgnoreFrom string 'a, button' 標識哪些子元素無法觸發(fā)拖拽事件,值為css-like選擇器
dragAllowFrom string null 標識哪些子元素可以觸發(fā)拖拽事件,值為css-like選擇器,如果值為null則表示所有子元素
resizeIgnoreFrom string 'a, button' 標識哪些子元素無法觸發(fā)調(diào)整大小的事件,值為css-like選擇器

4、事件

  • GridLayout 容器:
事件名 描述
layoutCreatedEvent 對應(yīng)Vue生命周期的created
layoutBeforeMountEvent 對應(yīng)Vue生命周期的beforeMount
layoutMountedEvent 對應(yīng)Vue生命周期的mounted
layoutReadyEvent 當完成mount中的所有操作時生成的事件
layoutUpdatedEvent 布局更新或柵格元素的位置重新計算事件
breakpointChangedEvent 斷點更改事件,每次斷點值由于窗口調(diào)整大小而改變
  • GridItem 子項:
事件名 描述
moveEvent 移動時的事件
resizeEvent 調(diào)整大小時的事件
movedEvent 移動后的事件
resizedEvent 調(diào)整大小后的事件
containerResizedEvent 柵格元素/柵格容器更改大小的事件(瀏覽器窗口或其他)

5、占位符樣式修改

直接覆蓋默認的class樣式

.vue-grid-item.vue-grid-placeholder {
    background: red;
    opacity: 0.2;
    transition-duration: 100ms;
    z-index: 2;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
}

.vue-grid-item.vue-grid-placeholder {
    background: green !important;
}

6、案例

注:本案例是按照vue3的寫法

  • HTML:
<div class="grid_box">
    <div class="left">
        <grid-layout
            v-model:layout="layoutLeft"
            :col-num="4"
            :row-height="50"
            :is-draggable="true"
            :is-resizable="true"
            :is-mirrored="false"
            :vertical-compact="true"
            :margin="[10, 10]"
            :use-css-transforms="true"
            ref="gridLeftRef"
        >
            <grid-item
                v-for="item in layoutLeft"
                :x="item.x"
                :y="item.y"
                :w="item.w"
                :h="item.h"
                :i="item.i"
                :key="item.i"
                @resized="handleGridSync"
                @moved="handleGridSync"
            >
                <div class="left_layout_item">
                    <div class="del_btn" @click="deleteGrid(item.i)">刪</div>
                    <span>{{ item.i }}</span>
                </div>
            </grid-item>
        </grid-layout>
    </div>
    <div class="right">
        <grid-layout
            v-model:layout="layoutRight"
            :col-num="4"
            :row-height="10"
            :is-draggable="true"
            :is-resizable="true"
            :is-mirrored="false"
            :vertical-compact="true"
            :margin="[10, 10]"
            :use-css-transforms="true"
            ref="gridRightRef"
        >
            <grid-item v-for="item in layoutRight" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.i">
                <div class="right_layout_item">{{ item.i }}</div>
            </grid-item>
        </grid-layout>
    </div>
</div>
  • 引入組件
import VueGridLayout from 'vue-grid-layout'
  • 數(shù)據(jù)源:
const gridLeftRef = ref<any>()
const gridRightRef = ref<any>()

const layoutLeft = ref([
    { i: '1', x: 0, y: 0, w: 2, h: 2 },
    { i: '2', x: 2, y: 0, w: 2, h: 2 },
    { i: '3', x: 0, y: 0, w: 2, h: 2 },
    { i: '4', x: 2, y: 0, w: 2, h: 2 }
])

const layoutRight = ref([
    { i: '1', x: 0, y: 0, w: 2, h: 2 },
    { i: '2', x: 2, y: 0, w: 2, h: 2 },
    { i: '3', x: 0, y: 0, w: 2, h: 2 },
    { i: '4', x: 2, y: 0, w: 2, h: 2 }
])
  • 處理方法:
// 處理Grid同步
const handleGridSync = () => {
    layoutLeft.value.forEach((item1) => {
        layoutRight.value.forEach((item2) => {
            if (item1.i === item2.i) {
                item2.x = item1.x
                item2.y = item1.y
                item2.w = item1.w
                item2.h = 2
            }
        })
    })
    gridLeftRef.value.layoutUpdate()
    gridLeftRef.value.updateHeight()
    gridRightRef.value.layoutUpdate()
    gridRightRef.value.updateHeight()
}

// 創(chuàng)造Grid
const createGrid = () => {
    let maxH = 0
    layoutLeft.value.forEach((item) => {
        if (item.y > maxH) maxH = item.y
    })
    const uid = createUuid()
    layoutLeft.value.push({ i: uid, x: 0, y: maxH, w: 2, h: 2 })
    layoutRight.value.push({ i: uid, x: 0, y: maxH, w: 2, h: 2 })
    handleGridSync()
}

// 刪除Grid
const deleteGrid = (id: string) => {
    const idx1 = layoutLeft.value.findIndex((item1) => item1.i === id)
    layoutLeft.value.splice(idx1, 1)
    const idx2 = layoutRight.value.findIndex((item2) => item2.i === id)
    layoutRight.value.splice(idx2, 1)
    handleGridSync()
}

本次分享就到這兒啦,我是@鵬多多,如果您看了覺得有幫助,歡迎評論,關(guān)注,點贊,轉(zhuǎn)發(fā),我們下次見~

PS:在本頁按F12,在console中輸入document.querySelectorAll('._2VdqdF')[0].click(),有驚喜哦

往期文章

個人主頁

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容