添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

vue-grid-layout是一个vue栅格拖动布局的组件. 官网

栅格布局,即网格布局,是一种新的 CSS 布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。

与flex布局的区别:

  1. Flexbox 是一维布局系统,适合做局部布局,比如导航栏组件。
  2. 网格布局是二维布局系统,可以更好的操作行和列,通常用于整个页面的规划。
  3. 虽然 Flexbox 也可以用于大的页面布局,但是没有 网格布局强大和灵活。二者结合使用更加轻松。二者从应用场景来说并不冲突。
  4. flex 布局一次只能处理一个维度上的元素布局,一行或者一列(flex-direction)。网格布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们布局的目的。

vue-grid-layout优点:

  1. 元素可拖动

  2. 元素可调整大小

  3. 边界检查拖动和调整大小

  4. 可以添加或删除窗口小部件而无需重建网格

  5. 布局可以 序列化

  6. 响应式布局

属性 GridLayout常用参数:

参数 含义 数据类型
layout 栅格的初始布局 Array
colNum 栅格系统的列数 Number 默认 12
rowHeight 每行的高度 Number 默认是单位是 px
isDraggable 栅格中的元素是否可拖拽 Boolean
isResizable 是否可以改变大小 Boolean
margin 栅格中的元素边距 Array

属性GridItem参数:

参数 含义 类型
i id 类型不限
x 格元素位于第几列 Number
y 元素位于第几行 Number
w 占几块(元素的初始宽度,值为 colWidth 的倍数) Number
h 元素的初始高度,值为 rowHeight 的倍数。 Number
isDraggable 元素是否可拖拽 Boolean
isResizable 元素是否可以改变大小 Boolean
static 是否为静态的(无法拖拽、调整大小或被其他元素移动) Boolean

每一个栅格元素grid-item上都可以添加监听器,用于监听移动和调整大小事件,这样父级Vue对象就可以收到通知。

GridLayout:

事件

含义

layoutCreatedEvent 对应Vue生命周期的created
layoutBeforeMountEvent 对应Vue生命周期的beforeMount
layoutMountedEvent 对应Vue生命周期的mounted
layoutReadyEvent 当完成mount中的所有操作时生成的事件
layoutUpdatedEvent 布局updated事件

GridItem:

事件

含义

moveRvent 移动时的事件
resizeRvent 调整大小时的事件
mocedRvent 移动后的事件
resizedRvent 调整大小后的事件
containerResizedRvent 栅格元素/栅格容器更改大小的事件(浏览器窗口或其他)
<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">
                <span class="text">{{item.i}}</span>
                <span class="remove" @click="removeItem(item.i)">x</span>
        </grid-item>
    </grid-layout>
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"},

源码解析:

1、栅格布局实现逻辑:

往grid-item上面放style样式,当标识是否使用CSS属性 useCssTransforms为true时,则使用transform来定位;(默认为true)

export function setTransform(top, left, width, height): Object {
	// Replace unitless items with px
	const translate = 'translate3d(' + left + 'px,' + top + 'px, 0)'
	return {
		transform: translate,
		WebkitTransform: translate,
		MozTransform: translate,
		msTransform: translate,
		OTransform: translate,
		width: width + 'px',
		height: height + 'px',
		position: 'absolute',

否则使用position定位,设置子元素的top、 left值;

export function setTopLeft(top, left, width, height): Object {
	return {
		top: top + 'px',
		left: left + 'px',
		width: width + 'px',
		height: height + 'px',
		position: 'absolute',

2、拖拽、缩放等交互;

使用的前端拖拽插件interact.js,提供拖,放,调整尺寸和多点触摸手势功能。

grid-item 通过interact的on方法,监听拖放、调整尺寸等事件。

//将当前拖动元素经过interact实例化之后,即可监听相应的事件 //拖拽事件 this.interactObj.on('dragstart dragmove dragend', function (event) { self.handleDrag(event) //缩放事件 this.interactObj.on('resizestart resizemove resizeend',function (event) { self.handleResize(event)

//元素拖拽时

      handleDrag(event) {
      //如果禁止拖拽、调整大小则reture
      if (this.static) return
      if (this.isResizing) return
      const position = getControlPosition(event) // 从事件中获取当前拖动点。这是用作偏移量的。  
      // Get the current drag point from the event. This is used as the offset.
      if (position === null) return // not possible but satisfies flow
      const { x, y } = position
      // let shouldUpdate = false;
      let newPosition = { top: 0, left: 0 }
      //通过监听拖拽事件,将拖拽的位置赋值给newPosition
      switch (event.type) {
        case 'dragstart': {
          this.previousX = this.innerX
          this.previousY = this.innerY
                //元素的父级视图定位
          let parentRect =event.target.offsetParent.getBoundingClientRect()//offsetParent为离自身最近且经过定位的父元素
          //元素的视图定位
          let clientRect = event.target.getBoundingClientRect()
          //是否为镜像反转
          //计算出当前模块left与top的距离 
          if (this.renderRtl) {
            newPosition.left = (clientRect.right - parentRect.right) * -1
          } else {
            newPosition.left = clientRect.left - parentRect.left
          newPosition.top = clientRect.top - parentRect.top
          this.dragging = newPosition
          console.log('dragstart====', this.dragging)
          this.isDragging = true
          break
        case 'dragend': {
          if (!this.isDragging) return
          let parentRect = event.target.offsetParent.getBoundingClientRect()
          let clientRect = event.target.getBoundingClientRect()
          //                        Add rtl support
          if (this.renderRtl) {
            newPosition.left = (clientRect.right - parentRect.right) * -1
          } else {
            newPosition.left = clientRect.left - parentRect.left
          newPosition.top = clientRect.top - parentRect.top
          // console.log("### drag end => " + JSON.stringify(newPosition));
          // console.log("### DROP: " + JSON.stringify(newPosition));
          this.dragging = null
          console.log('dragend====', this.dragging)
          this.isDragging = false
          // shouldUpdate = true;
          break
        case 'dragmove': {
          const coreEvent = createCoreData(this.lastX, this.lastY, x, y)
          //                        Add rtl support
          if (this.renderRtl) {
            newPosition.left = this.dragging.left - coreEvent.deltaX
          } else {
            newPosition.left = this.dragging.left + coreEvent.deltaX
          newPosition.top = this.dragging.top + coreEvent.deltaY
          this.dragging = newPosition
          console.log('dragmove====', this.dragging)
          break
      // Get new XY
      //根据left与top的计算出当前模块在XY的值(通过四舍五入的方式)
      let pos
      if (this.renderRtl) {
        pos = this.calcXY(newPosition.top, newPosition.left)
      } else {
        pos = this.calcXY(newPosition.top, newPosition.left)
      this.lastX = x
      this.lastY = y
      //仅用来打印
      if (this.innerX !== pos.x || this.innerY !== pos.y) {
        this.$emit('move', this.i, pos.x, pos.y)
        event.type === 'dragend' &&
        (this.previousX !== this.innerX || this.previousY !== this.innerY)
        this.$emit('moved', this.i, pos.x, pos.y)
      //将拖动时的位置数据传给容器,容器对layout与占位空间赋值
      this.eventBus.$emit(
        'dragEvent',
        event.type,
        this.i,
        pos.x,
        pos.y,
        this.innerH,
        this.innerW

// 拖渲染页面

      dragEvent: function (eventName, id, x, y, h, w) {
      //获取到当前的拖动的元素
      let l = getLayoutItem(this.layout, id)
      //GetLayoutItem sometimes returns null object
      if (l === undefined || l === null) {
        l = { x: 0, y: 0 }
      //当拖动为dragmove、dragstart时,赋值占位符的位置
      if (eventName === 'dragmove' || eventName === 'dragstart') {
        this.placeholder.i = id
        this.placeholder.x = l.x
        this.placeholder.y = l.y
        this.placeholder.w = w
        this.placeholder.h = h
        this.$nextTick(function () {
          this.isDragging = true
        //this.$broadcast("updateWidth", this.width);
        this.eventBus.$emit('updateWidth', this.width)
      } else {
        this.$nextTick(function () {
          this.isDragging = false
      // Move the element to the dragged location.
      //获取到其他元素的级联动作,将元素移动到拖动位置。
      this.layout = moveElement(
        this.layout,
        true,
        this.preventCollision//防止碰撞属性
      compact(this.layout, this.verticalCompact)
      // needed because vue can't detect changes on array element properties
      //让vue检测到数组元素属性的变化
      this.eventBus.$emit('compact')
      this.updateHeight()
      if (eventName === 'dragend') this.$emit('layout-updated', this.layout)

相关问题:

  1. 标识栅格元素是否可拖拽(isDraggable)该属性只能将元素向下排,并不能形成左右替换的形式,并且在该组件中也没有元素互相替换位置这种属性;
  2. GridItem的XY参数只能为整数;
  3. 没有下边界,发生碰撞的时候块会无限的往下移动;

    视图页面中每一个面板都可拖拽,可随意放大放小,体验还是不错的。

vue-grid-layout是一个vue栅格拖动布局的组件.官网特点: 元素可拖动 元素可调整大小 边界检查拖动和调整大小 可以添加或删除窗口小部件而无需重建网格 布局可以序列化 标识栅格元素是否可拖拽该属性只能将元素向下排,并不能形成左右替换的形式 属性 GridLayout常用参数:参数 含义 数据类型 colNum 将一行分为多少块 数字 默认 12 rowHeight 行高 ...
布局//上半部分 &lt;com.example.lenovo.pandachannel.base.GridLayout android:id="@+id/drable_grid1" android:layout_width="match_parent" android:layout_height="wrap_content" and...
最近领导要求系统首页布局改一下,类似于自助建站那种首页可以实现模块的自定义拖拽,并可以实现保存等功能,一下让我这种VUE新手有点慌张,上网上搜一下也没有对应的结局方案,那就自己写吧。不过最终磕磕绊绊也算是实现了。废话不多说,先上功能。 首先首页实现功能卡片定义,并可自定义调整大小存储等,卡片内容随意定义 多种布局可选,布局也可以随意定义 功能卡片的增删等功能(基于layout面板上存在卡片展...
<div :style="setLeftStyle()" class="view"></div> <div id="line" class="line"></div> <div :style="setRightStyle()" class="view"></div> $ npm install @geospoc/v-grid-layout import VueGridLayout from '@geospoc/v-grid-layout' ; 添加到其他Vue组件 export default { components : { GridLayout : VueGridLayout . G npm install vue-responsive-grid-layout import {VueResponsiveGridLayout, VueGridItem, VueGridLayout } from 'vue-responsive-grid-layout' Vue.component # serve with hot reload at localhost:8080 npm run dev # build for production with minification npm run build # build for production and view the bundle analyzer report npm run build --report 有关工作原理的详细说明,请查看的和。
vue-grid-layout 一个可以拖拽vue 布局方案 https://www.cnblogs.com/yasoPeng/p/9961732.html // 地址 install with npm npm install vue-grid-layout --save install with yarn yarn add vue-grid-layout import Vue...
http://www.eoeandroid.com/thread-71624-1-1.html 自定义gridview  自定义view  自定义adapter  ,其中gridview自定义参照了论坛中代码    我改了蛮多   加上了详细的中文注释,
Vue-grid-layout 是一个基于 Vue.js 的响应式网格布局系统,可以帮助你轻松地实现桌面拖拽布局功能。下面是一个简单的例子: 1. 首先,你需要安装 vue-grid-layout: npm install vue-grid-layout 2. 在 Vue 组件中引入 vue-grid-layout: ```javascript import VueGridLayout from 'vue-grid-layout'; 3. 在 template 中使用 vue-grid-layout: ```html <vue-grid-layout :layout="layout" :col-num="12" :row-height="30" :is-draggable="true" :is-resizable="true"> <div v-for="item in layout" :key="item.i">{{ item.i }}</div> </vue-grid-layout> 其中,`layout` 是一个数组,用于定义每个网格的位置和大小。`col-num` 定义了网格布局的列数,`row-height` 定义了每行网格的高度,`is-draggable` 和 `is-resizable` 分别表示是否可拖拽和可调整大小。 4. 在 JavaScript 中定义 `layout` 数组: ```javascript data() { return { layout: [ { i: 'a', x: 0, y: 0, w: 1, h: 2 }, { i: 'b', x: 1, y: 0, w: 3, h: 2 }, { i: 'c', x: 4, y: 0, w: 1, h: 2 } 其中,`i` 表示网格的 ID,`x` 和 `y` 表示网格的左上角坐标,`w` 和 `h` 表示网格的宽度和高度。 这样,你就可以实现一个简单的网格布局,并且可以拖拽和调整网格的大小。更多详细的用法可以参考 vue-grid-layout 的官方文档。