vue-grid-layout 的使用

陆仲渊
2023-12-01

vue-grid-layout中文文档

使用理由:这个瀑布流是可以拖拽的

碰到的问题

在安装完这个插件之后,在IE上无法打开,并报错缺少:,最终是下面这篇文章解决问题
Vue项目下IE报错 SCRIPT1003: 缺少 ‘:’,导致页面空白的解决方案
主要原因就是第三方库的兼容性问题,把vue-grid-layout引入到vue.config.js文件下的transpileDependencies集合中:

module.exports = {
  ...
  transpileDependencies: ['element-ui', 'proxy-polyfill' , 'vue-grid-layout'],
}

基于layout的组件

我的需求值只需要显示3-4列的样子,所以我需要多少列就将col-num设为多少,便于后续的位置计算。这里的组件实现了对接收的数组进行构造,生成可供gird-layout使用的数据,最后返回拖拽调换后的顺序。

<template>
  <grid-layout
    :layout.sync="layout"
    :col-num="colNum"
    :row-height="rowHeight"
    :is-draggable="isDraggable"
    :is-resizable="isResizable"
    :is-mirrored="isMirrored"
    :margin="marginArr"
    :responsive="isResponsive"
    :useStyleCursor="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"
      class="item"
      drag-allow-from=".dragger"
      @moved="movedEvent"
    >
    	<!-- 將数据外传 -->
       <slot name="item" :item="item"></slot>
    </grid-item>
  </grid-layout>
</template>

<script>
import * as _ from 'lodash'
import VueGridLayout from 'vue-grid-layout'
export default {
  components: {
    GridLayout: VueGridLayout.GridLayout,
    GridItem: VueGridLayout.GridItem,
  },
  props: {
    indData: {
      type: Array,
      default: () => [],
    },
    colNum: {
      type: Number,
      default: 3,
    },
    rowHeight: {
      type: Number,
      default: 100,
    },
    isDraggable: {
      type: Boolean,
      default: false
    },
    isResizable: {
      type: Boolean,
      default: false
    },
    isMirrored: {
      type: Boolean,
      default: false
    },
    isResponsive: {
      type: Boolean,
      default: false
    },
    marginArr:{
      type: Array,
      default: () => [10, 20],
    },
    // 根据这个键返回排序后的数组,如果不设置,就返回整个排序后的对象
    sortKey:{
      type:String,
      default:''
    }
  },
  data() {
    return {
      layout: [
        { x: 0, y: 0, w: 1, h: 1, i: '0', id: 1 },
        { x: 1, y: 0, w: 1, h: 1, i: '1', id: 2 },
        { x: 2, y: 0, w: 1, h: 1, i: '2', id: 3 },
        { x: 0, y: 1, w: 1, h: 1, i: '3', id: 4 },
        { x: 1, y: 1, w: 1, h: 1, i: '4', id: 5 },
      ],
    }
  },
  methods: {
    // 构造数据
    createLayout(arr) {
      const col = this.colNum
      const res = arr.map((item, index) => {
        item.x = index % col
        item.y = parseInt(index / col)
        item.w = 1
        item.h = 1
        item.i = index + ''
        return item
      })
      return res
    },
    // 移动之后的事件
    movedEvent(i, newX, newY) {
      const arr = this.getMovedOrder().map((item) => {
        if(!this.sortKey){
          return item
        }else{
          return item[this.sortKey]
        }
      })
      this.$emit('moved',arr)
    },
    getMovedOrder() {
      const newLayout = [...this.layout]
      // 先按y(行)排,再按x(列)排序
      newLayout.sort((a, b) => {
        if (a.y !== b.y) {
          return a.y - b.y
        } else {
          return a.x - b.x
        }
      })
      return newLayout
    },
  },

  watch: {
    indData:{
      handler(arr) {
        // 这里需要深拷贝,否则之后的操作会改变这个对象
        this.layout = this.createLayout(_.cloneDeep(arr))
      },
      deep: true,
      immediate:true
    },
  },
}
</script>

<style lang="scss" scoped>

.item {
  touch-action: none;
  width: 100%;
  height:100%;
  border: 1px solid #5592e5;
  // transition: all .3s;
  // cursor: move;
  &:hover{
    transform: scale(1.05,1.05); 
  }
}

</style>

需要设置响应式的话,就对cols进行相应设置,breakpoints直接使用默认即可

:responsive="true"
:cols="{ lg: 3, md: 2, sm: 2, xs: 1, xxs: 1 }"
:breakpoints="{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }"  

使用

<template>
   <grid-fall :colNum="3" :rowHeight="100" :indData="indData" :isDraggable="true" @moved="getMovedData" :sortKey="'id'">
     <template slot="item" slot-scope="data">
       子组件循环中的值:{{data.item.i}}
       <!-- button 无效 -->
       <el-button class="dragger">拖动(实际无效)</el-button>
       <el-button class="no-drag">不可拖动</el-button>
       <p class="dragger">拖动图标(可拖动)</p>
     </template>
  </grid-fall>
</template>

<script>

import GridFall from '@/components/indicator/combine/GridFall.vue'
export default {
  components:{
    GridFall
  },
  data() {
    return {
      // 传入的对象数组
      indData: [
        { id:0 },
        { id:1 },
        { id:2 },
        { id:3 },
        { id:4 },
        { id:5 },
      ]
    }
  },
  methods:{
    getMovedData(v){
      console.log('拖拽排序之后:',v)
    }
  }
}
</script>
 类似资料: