draggable + grid 拖拽插件 + 网格布局 动态生成首页模版

这篇具有很好参考价值的文章主要介绍了draggable + grid 拖拽插件 + 网格布局 动态生成首页模版。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景:

        1、首页模板由多个子组件组成,如图表、新闻、公告、轮播图等,一般都由前端引入子组件,写在固定的位置上,最终形成一个固定的首页模板;

        2、像这样直接在代码中写死的首页没有灵活性,不同用户想展示出来的首页模板千篇一律;

        3、若是首页模板可以根据用户自己的需求拖拽生成,首页模板的灵活性与交互性将会两者兼备。

描述:

        1、通过使用draggable拖拽插件可实现自由拖拽子组件;

        【拖拽插件 draggable 详解及意见 - 掘金】

        2、draggable可实现左右拖拽,若想完全根据用户的意愿上下左右都可拖拽,在这里我使用的是grid网格布局实现相应功能。

        【CSS Grid 网格布局教程 - 阮一峰的网络日志】

测试案例展示:

拖拽配置首页组件,Vue,css,前端,vue.js,javascript

        1)左边为子组件列表,暂时使用色块代表可组成首页的所有组件;

        2)右边为拖拽区域,拖拽区域由grid网格布局作为背景板,子组件可根据手动设置的网格布局的大小进行放置;

        3)拖拽后的子组件提供了编辑、删除、拖拽三项功能,编辑可控制该子组件的宽高比例,删除后则回到左部组件列表中,拖拽可实现各个子组件之间的位置交换。

代码展示:

一、子组件列表

        循环dataList拿到子组件对象数组,鼠标放置时增加遮罩层,显示该子组件的宽高比例、名称;draggable是可拖拽的子组件列表区域,通过dragOptions1进行对拖拽区域内容的控制。

<draggable v-bind="dragOptions1" class="left" v-model="dataList">
   <div
      :data-width="item.width"
      :data-height="item.height"
      :class="[
         'item',
         'item_width_' + item.width,
         'item_height_' + item.height,
         'item_' + item.component
      ]"
      v-for="(item, index) in dataList"
      :key="index"
     >
      <div class="cover">
         <span>{{ item.title }}{{ item.width }}×{{ item.height }}</span>
      </div>
   </div>
</draggable>


dragOptions1() {
  return {
      animation: 300,
      group: {
          name:'group',//名称相同的分组可以相互拖拽
          pull:true, //是否允许拖出当前组
          put:true //是否允许拖入当前组
      },
      chosenClass: "sortable-btn",
      forceFallback: true,
      handle: ".item" // 只有按住拖动手柄才能使列表单元进行拖动
  }
},

拖拽配置首页组件,Vue,css,前端,vue.js,javascript

二、拖拽区域展示

        dataList2存放从dataList中拖拽出来的子组件数据信息,同样增加遮罩层moveDialog,展示子组件的功能按钮:编辑、删除。

<draggable v-bind="dragOptions2" class="rightBox" :list="dataList2">
  <div
    :class="[
      'item',
      'item_width_' + item.width,
      'item_height_' + item.height,
    ]"
    v-for="(item, index) in dataList2"
    :key="index"
  >
    <div class="moveDialog">
      <Button type="primary" size="small" class="edit" @click="edit(item)">编 辑</Button>
      <Button type="primary" size="small" class="del" @click="del(item)">删 除</Button>
    </div>
    <components :ref='item.component' :is="item.component" style="pointer-events: none;cursor: default;"></components>
  </div>
</draggable>


dragOptions2() {
  return {
    animation: 300,
    group: {
      name:'group',
      pull:false,
      put:true
    },
    ghostClass: 'ghost',
    forceFallback: true,
    handle: ".moveDialog"
  }
}

拖拽配置首页组件,Vue,css,前端,vue.js,javascript

 三、编辑、删除功能

        编辑在这里只写了控制子组件的宽高比例、删除则会将已经拖拽的组件撤回到子组件列表中,具体代码实现如下:

<Modal
  v-model="editModal"
  class="edit-modal"
  :transfer='false'
  :title="`编辑组件信息`"
  @on-ok="submitFormEdit"
  @on-cancel="handleCancelEdit"
  :mask-closable="false">
    <Form ref="formValidate" :model="formValidate" :label-width="100" :rules="ruleValidate">
        <p style="color:gray;font-size:12px;margin:0 0 5px 100px">*(推荐宽度比例:4、8、12、16。)</p>
        <FormItem label="宽度比例:" prop="width">
            <InputNumber v-model="formValidate.width" placeholder="请输入宽度比例"></InputNumber>
        </FormItem>
        <p style="color:gray;font-size:12px;margin:0 0 5px 100px">*(建议高度比例:大于等于当前默认高度。)</p>
        <FormItem label="高度比例:" prop="height">
            <InputNumber v-model="formValidate.height" placeholder="请输入高度比例"></InputNumber>
        </FormItem>
    </Form>
    <p style="color:red;font-size:12px;">*(提示:以上给出的是较为合适的宽高比例,可酌情调整,不建议暴力调整比例。)</p>
    <div slot="footer" align="right">
        <Button @click="handleCancelEdit">取 消</Button>
        <Button type="primary" @click="submitFormEdit">确 定</Button>
    </div>
</Modal>


// 编辑按钮
edit(row) {
    this.editModal = true
    this.formValidate = JSON.parse(JSON.stringify(row))
},
// 删除按钮
del(data){
  let dataList2 = JSON.parse(JSON.stringify(this.dataList2))
  this.dataList2 = dataList2.filter(item => item.chartId !== data.chartId)
  this.dataList.push(data)
},
// 编辑弹窗确定按钮
submitFormEdit: function () {
  this.$refs['formValidate'].validate((valid) => {
    if (valid) {
      this.dataList2.map(item => {
        if(item.chartId === this.formValidate.chartId){
          item.width = this.formValidate.width
          item.height = this.formValidate.height
        }
        return item
      })
      this.handleCancelEdit()
      this.$Message.success('编辑成功!')
    } else {
      console.log('检验不通过!');
    }
  })
},
// 编辑弹窗取消按钮
handleCancelEdit() {
  this.editModal = false
  this.$refs.formValidate.resetFields()
  this.formValidate = {
    width: 4,
    height: 1
  }
}

拖拽配置首页组件,Vue,css,前端,vue.js,javascript四、拖拽插件的引入、使用及网格布局的使用

(在这里就不过多解释啦~,参考下面提示的文章了解draggable的使用和grid的相关概念)

 【拖拽插件 draggable 详解及意见 - 掘金】 【CSS Grid 网格布局教程 - 阮一峰的网络日志】

全部代码实现:

<template>
  <div class='test'>
    <main>
      <draggable v-bind="dragOptions1" class="left" v-model="dataList">
        <div
          :data-width="item.width"
          :data-height="item.height"
          :class="[
            'item',
            'item_width_' + item.width,
            'item_height_' + item.height,
            'item_' + item.component
          ]"
          v-for="(item, index) in dataList"
          :key="index"
        >
          <div class="cover">
            <span>{{ item.title }}{{ item.width }}×{{ item.height }}</span>
          </div>
        </div>
      </draggable>
      <div class="right">
        <draggable v-bind="dragOptions2" class="rightBox" :list="dataList2">
          <div
            :class="[
              'item',
              'item_width_' + item.width,
              'item_height_' + item.height,
            ]"
            v-for="(item, index) in dataList2"
            :key="index"
          >
            <div class="moveDialog">
              <Button type="primary" size="small" class="edit" @click="edit(item)">编 辑</Button>
              <Button type="primary" size="small" class="del" @click="del(item)">删 除</Button>
            </div>
            <components :ref='item.component' :is="item.component" style="pointer-events: none;cursor: default;"></components>
          </div>
        </draggable>
      </div>
    </main>
    <Modal
      v-model="editModal"
      class="edit-modal"
      :transfer='false'
      :title="`编辑组件信息`"
      @on-ok="submitFormEdit"
      @on-cancel="handleCancelEdit"
      :mask-closable="false">
        <Form ref="formValidate" :model="formValidate" :label-width="100" :rules="ruleValidate">
            <p style="color:gray;font-size:12px;margin:0 0 5px 100px">*(推荐宽度比例:4、8、12、16。)</p>
            <FormItem label="宽度比例:" prop="width">
                <InputNumber v-model="formValidate.width" placeholder="请输入宽度比例"></InputNumber>
            </FormItem>
            <p style="color:gray;font-size:12px;margin:0 0 5px 100px">*(建议高度比例:大于等于当前默认高度。)</p>
            <FormItem label="高度比例:" prop="height">
                <InputNumber v-model="formValidate.height" placeholder="请输入高度比例"></InputNumber>
            </FormItem>
        </Form>
        <p style="color:red;font-size:12px;">*(提示:以上给出的是较为合适的宽高比例,可酌情调整,不建议暴力调整比例。)</p>
        <div slot="footer" align="right">
            <Button @click="handleCancelEdit">取 消</Button>
            <Button type="primary" @click="submitFormEdit">确 定</Button>
        </div>
    </Modal>
  </div>
</template>
<script>
import draggable from "vuedraggable";
import red from "./test/red.vue";
import orange from "./test/orange.vue";
import yellow from "./test/yellow.vue";
import green from "./test/green.vue";
import bfa from "./test/bfa.vue";
import blue from "./test/blue.vue";
import purple from "./test/purper.vue";
import pink from "./test/pink.vue";
import fff from "./test/fff.vue";
import black from "./test/black.vue";
export default {
 name:'test',
  components: {
  red,
  orange,
  yellow,
  green,
  bfa,
  blue,
  purple,
  pink,
  fff,
  black,
  draggable
  },
  data () {
    const widthRule = (rule, value, callback) => {
      if(!value){
        callback(new Error('请输入宽度比例!'))
      }else if(!/^[1-9]([0-9])*$/g.test(value)){
        callback(new Error('只能输入正整数!'))
      }else if(value < 4){
        callback(new Error('宽度比例不能小于4!'))
      }else if(value > 16){
        callback(new Error('宽度比例不能大于16!'))
      }else{
        callback()
      }
    }
    const heightRule = (rule, value, callback) => {
      if(!value){
        callback(new Error('请输入高度比例!'))
      }else if(!/^[1-9]([0-9])*$/g.test(value)){
        callback(new Error('只能输入正整数!'))
      }else{
        callback()
      }
    }
    return {
      // 拖拽总数据
      dataList: [
        {
          chartId: '1',
          title: "红色",
          name: "red",
          width: 4,
          height: 2,
          component: "red",
        },
        {
          chartId: '2',
          title: "橙色",
          name: "orange",
          width: 12,
          height: 2,
          component: "orange",
        },
        {
          chartId: '3',
          title: "黄色",
          name: "yellow",
          width: 16,
          height: 1,
          component: "yellow",
        },
        {
          chartId: '4',
          title: "绿色",
          name: "green",
          width: 4,
          height: 6,
          component: "green",
        },
        {
          chartId: '5',
          title: "青色",
          name: "bfa",
          width: 4,
          height: 6,
          component: "bfa",
        },
        {
          chartId: '6',
          title: "蓝色",
          name: "blue",
          width: 4,
          height: 3,
          component: "blue",
        },
        {
          chartId: '7',
          title: "紫色",
          name: "purple",
          width: 8,
          height: 3,
          component: "purple",
        },
        {
          chartId: '8',
          title: "粉色",
          name: "pink",
          width: 4,
          height: 3,
          component: "pink",
        },
        {
          chartId: '9',
          title: "白色",
          name: "fff",
          width: 12,
          height: 3,
          component: "fff",
        },
        {
          chartId: '10',
          title: "黑色",
          name: "black",
          width: 4,
          height: 3,
          component: "black",
        }
      ],
      // 生成页面数据 
      dataList2: [],
      droplist: [],
      // 编辑弹窗
      editModal: false,
      // 编辑表单
      formValidate: {
        width: 4,
        height: 1
      },
      // 编辑表单限制
      ruleValidate: {
        width: [
          { required: true, validator: widthRule }
        ],
        height: [
          { required: true, validator: heightRule }
        ]
      }
     }
  },
  computed: {
    dragOptions1() {
      return {
          animation: 300,
          group: {
              name:'group',//名称相同的分组可以相互拖拽
              pull:true, //是否允许拖出当前组
              put:true //是否允许拖入当前组
          },
          chosenClass: "sortable-btn",
          forceFallback: true,
          handle: ".item" // 只有按住拖动手柄才能使列表单元进行拖动
      }
    },
    dragOptions2() {
      return {
        animation: 300,
        group: {
          name:'group',
          pull:false,
          put:true
        },
        ghostClass: 'ghost',
        forceFallback: true,
        handle: ".moveDialog"
      }
    }
  },
  mounted() {},
  methods: {
    watchDrag() {},
    // 编辑按钮
    edit(row) {
        this.editModal = true
        this.formValidate = JSON.parse(JSON.stringify(row))
    },
    // 删除按钮
    del(data){
      let dataList2 = JSON.parse(JSON.stringify(this.dataList2))
      this.dataList2 = dataList2.filter(item => item.chartId !== data.chartId)
      this.dataList.push(data)
    },
    // 编辑弹窗确定按钮
    submitFormEdit: function () {
      this.$refs['formValidate'].validate((valid) => {
        if (valid) {
          this.dataList2.map(item => {
            if(item.chartId === this.formValidate.chartId){
              item.width = this.formValidate.width
              item.height = this.formValidate.height
            }
            return item
          })
          this.handleCancelEdit()
          this.$Message.success('编辑成功!')
        } else {
          console.log('检验不通过!');
        }
      })
    },
    // 编辑弹窗取消按钮
    handleCancelEdit() {
      this.editModal = false
      this.$refs.formValidate.resetFields()
      this.formValidate = {
        width: 4,
        height: 1
      }
    }
  }
}
</script>
<style lang='less' scoped>
   .test{
    height: calc( 100vh - 60px);
    position: relative;
    main{
      height: 100%;
      position: relative;
      padding-left: 300px;
        .left{
          position: absolute;
          left: 0;
          float: left;
          width: 300px;
          height: 100%;
          background-color: rgb(238, 238, 240);
          overflow-y: auto;
          overflow-x: hidden;
          padding: 10px;
          .item{
            position: relative;
            height: 180px;
            margin-bottom: 10px;
            white-space: nowrap;
            cursor: pointer;
            background: rgb(239, 243, 247);
            border: 1px solid #DCDFE6;
            border-color: #DCDFE6;
            color: #606266;
            outline: none;
            padding: 12px 20px;
            font-size: 14px;
            border-radius: 4px;
            .cover{
              position: absolute;
              top:0;
              left: 0;
              height: 100%;
              transition: all .2s;
              width: 100%;
              text-align: center;
              background-color: #0006;
              opacity: 0;
              span{
                line-height: 180px;
                color:#fff;
                font-size: 16px;
              }
            }
            &:hover{
              .cover{
                opacity: 1;
              }
            }
          }
          .sortable-btn{
            box-shadow: 0 0 4px 4px #9992;
          }
          .item_red{
            background: url(../../assets/images/red.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_orange{
            background: url(../../assets/images/orange.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_yellow{
            background: url(../../assets/images/yellow.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_green{
            background: url(../../assets/images/green.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_bfa{
            background: url(../../assets/images/bfa.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_blue{
            background: url(../../assets/images/blue.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_purple{
            background: url(../../assets/images/purper.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_pink{
            background: url(../../assets/images/pink.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_fff{
            background: url(../../assets/images/fff.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
          .item_black{
            background: url(../../assets/images/black.png);
            background-size: 100% 100%;
            background-repeat: no-repeat;
          }
        }
        .right{
          position: relative;
          height: 100%;
          overflow: auto;
          background-color: rgb(239, 243, 247);
          .rightBox{
            position: relative;
            display: grid;
            grid-template-columns: repeat(16, 1fr);
            grid-auto-rows: 100px; 
            grid-auto-flow: row dense;
            gap: 15px;
            padding: 10px;
            // min-height: 650px;
            padding-bottom: 20px;
            .ghost{
              opacity: .7;
              span{
                display: none;
              }
              &::before{
                content: "";
                position: absolute;
                top:0;
                left: 0;
                padding: 8px;
                cursor: pointer;
                // background-color: red;
              }
              &::after{
                content: "(^_^)~";
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
              }
            }
            .item{
              position: relative;
              background-color: #fff;
              border-radius: 4px;
              box-shadow: 0 0 2px 2px #9991;
              .edit{
                display: none;
                position: absolute;
                top: 10px;
                right: 75px;
                line-height: 20px;
                cursor: pointer;
              }
              .del{
                display: none;
                position: absolute;
                top: 10px;
                right: 10px;
                line-height: 20px;
                cursor: pointer;
              }
              .moveDialog{
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                opacity: 0;
                background-color: gray;
                z-index: 999;
              }
              .contentBox{
                pointer-events: none;
                cursor: default;
              }
            }
            .item:hover{
              .edit{
                display: block;
                opacity: 1;
              }
              .del{
                display: block;
                opacity: 1;
              }
              .moveDialog{
                opacity: 0.9;
              }
            }
            .item_width_1{
                grid-column-start: span 1;
                width: 100%;
            }
            .item_width_2{
                grid-column-start: span 2;
                width: 100%;
            }
            .item_width_3{
                grid-column-start: span 3;
                width: 100%;
            }
            .item_width_4{
                grid-column-start: span 4;
                width: 100%;
            }
            .item_width_5{
                grid-column-start: span 5;
                width: 100%;
            }
            .item_width_6{
                grid-column-start: span 6;
                width: 100%;
            }
            .item_width_7{
                grid-column-start: span 7;
                width: 100%;
            }
            .item_width_8{
                grid-column-start: span 8;
                width: 100%;
            }
            .item_width_9{
                grid-column-start: span 9;
                width: 100%;
            }
            .item_width_10{
                grid-column-start: span 10;
                width: 100%;
            }
            .item_width_11{
                grid-column-start: span 11;
                width: 100%;
            }
            .item_width_12{
                grid-column-start: span 12;
                width: 100%;
            }
            .item_width_13{
                grid-column-start: span 13;
                width: 100%;
            }
            .item_width_14{
                grid-column-start: span 14;
                width: 100%;
            }
            .item_width_15{
                grid-column-start: span 15;
                width: 100%;
            }
            .item_width_16{
                grid-column-start: span 16;
                width: 100%;
            }
            .item_height_1{
                grid-row-start: span 1;
                // line-height: 100px;
            }
            .item_height_2{
                grid-row-start: span 2;
                // line-height: 200px;
            }
            .item_height_3{
                grid-row-start: span 3;
                // line-height: 300px;
            }
            .item_height_4{
                grid-row-start: span 4;
                // line-height: 400px;
            }
            .item_height_5{
                grid-row-start: span 5;
                // line-height: 400px;
            }
            .item_height_6{
                grid-row-start: span 6;
                // line-height: 400px;
            }
            .item_height_7{
                grid-row-start: span 7;
                // line-height: 400px;
            }
            .item_height_8{
                grid-row-start: span 8;
                // line-height: 400px;
            }
            .item_height_9{
                grid-row-start: span 9;
                // line-height: 400px;
            }
            .item_height_10{
                grid-row-start: span 10;
                // line-height: 400px;
            }
            .item_height_11{
                grid-row-start: span 11;
                // line-height: 400px;
            }
            .item_height_12{
                grid-row-start: span 12;
                // line-height: 400px;
            }
            .item_height_13{
                grid-row-start: span 13;
                // line-height: 400px;
            }
            .item_height_14{
                grid-row-start: span 14;
                // line-height: 400px;
            }
            .item_height_15{
                grid-row-start: span 15;
                // line-height: 400px;
            }
            .item_height_16{
                grid-row-start: span 16;
                // line-height: 400px;
            }
          }
        }
      }
    }
  </style>

(该案例使用vue2框架书写,实现效果请观看视频https://live.csdn.net/v/284266)

前端小白积累经验篇~~文章来源地址https://www.toymoban.com/news/detail-791173.html

到了这里,关于draggable + grid 拖拽插件 + 网格布局 动态生成首页模版的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 手撸前端 Grid 拖拽布局

    最近有个需求需要实现自定义首页布局,需要将屏幕按照 6 列 4 行进行等分成多个格子,然后将组件可拖拽对应格子进行渲染展示。 示例 对比一些已有的插件,发现想要实现产品的交互效果,没有现成可用的。本身功能并不是太过复杂,于是决定自己基于 vue 手撸一个简易的

    2024年02月05日
    浏览(32)
  • 最强大的布局方案——网格Grid布局万字详解

    Grid 布局又称网格布局,是W3C提出的一个二维布局系统,它与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但它们也存在重大区别。Flex 布局是轴线布局,只能指定\\\"项目\\\"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成\\\"行\\\"和\\\"列\\\",产生单

    2024年02月08日
    浏览(52)
  • Unity 网格布局控件-Grid Layout Group

    Unity 网格布局控件-Grid Layout Group是Unity中的UGUI控件,用于在 UI 中创建网格布局, 它的作用是:自动将子对象排列成网格,即我们可以通过该组件对子对象按行和列的形式排列,根据指定的约束条件自动调整它们的大小和位置。通常我们使用它创建具有规律排列的 UI 元素,如

    2024年02月04日
    浏览(50)
  • 【CSS Grid网格布局】常用属性,示例代码解读

    grid-template-columns/grid-template-rows:用于定义网格的列和行的大小和数量。可以指定具体的尺寸值(如px、em等),也可以使用fr单位表示剩余空间的比例分配。 grid-column-gap/grid-row-gap:用于定义网格的列间距和行间距。可以使用具体的尺寸值或百分比。 grid-template-areas:用于定义

    2024年02月12日
    浏览(45)
  • 低代码开发之vue.draggable的使用(初阶:组件化拖拽生成简单页面)

    效果展示 vue.draggable 安装 使用 vue.draggable 相关属性 事件 Demo完整代码 更多详见draggable官网=https://www.itxst.com/vue-draggable/tutorial.html

    2024年02月19日
    浏览(40)
  • 低代码开发之vue.draggable的使用(进阶:组件化拖拽生成功能页面)

    效果展示: 前言:随着各公司定制化需求的不断攀升,公司对低代码、组态化的开发需求日渐迫切。也许是研发任务节点将至,也许是为顺应时代潮流,我也是去学习并实践了一番。如图所示。 功能简介: 左侧组件区域特意做了选中态,小眼睛预览浮框态等交互,右侧内容区

    2024年03月23日
    浏览(52)
  • 项目中拖拽元素,可以使用html的draggable属性,当然也可以用第三方插件interact

    html的draggable属性需要自己写逻辑,用人家封装好的代码简单逻辑清楚,非常香 链接: https://blog.csdn.net/vvv3171071/article/details/122705408

    2024年02月08日
    浏览(54)
  • 【算法】Maximize Grid Happiness 最大化网格幸福感 动态规划

    给你四个整数 m、n、introvertsCount 和 extrovertsCount 。有一个 m x n 网格,和两种类型的人:内向的人和外向的人。总共有 introvertsCount 个内向的人和 extrovertsCount 个外向的人。 请你决定网格中应当居住多少人,并为每个人分配一个网格单元。 注意,不必 让所有人都生活在网格中

    2024年02月11日
    浏览(38)
  • vue3拖拽布局+动态组件+自适应布局

    1.拖拽布局插件 Vue Grid Layout -️ 适用Vue.js的栅格布局系统 可拖动和可调整大小栅格布局的Vue组件。 https://jbaysolutions.github.io/vue-grid-layout/zh/ //在package.json中dependencies下添加下面插件库,并执行命令npm install  \\\"vue-grid-layout\\\": \\\"^3.0.0-beta1\\\",  2.拖拽页面代码 3.图表子组件代码

    2024年02月11日
    浏览(42)
  • HTML5新增的拖拽属性draggable,怎么实现拖拽?

    1、draggable 属性规定元素是否可拖动。 2、提示: 链接和图像默认是可拖动的。 3、提示: draggable 属性经常用于拖放操作。 注意:draggable 属性是 HTML5 新增的。 设置属性值 值 描述 true 规定元素是可拖动的。 false 规定元素是不可拖动的。 auto 使用浏览器的默认特性。 代码演

    2024年02月16日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包