基于draggable拖拽DEMO

 

demo

<template>
  <el-dialog :visible="dragAndDropFormDialog" title="测试拖拽" fullscreen center @close="btnCancel">
    <div class="dropBox">
      <!--使用draggable组件-->
      <div class="itxst">
        <div class="col">
          <div class="title">元素</div>
          <draggable
            v-model="arr1"
            group="site"
            animation="300"
            drag-class="dragClass"
            ghost-class="ghostClass"
            chosen-class="chosenClass"
            @start="onStart"
            @end="onEnd"
            @change="change"
          >
            <transition-group>
              <div v-for="(item, index) in arr1" :key="index" class="item">
                <div v-if="item.innerHTML == 'title1'" class="title1">{{ item.name }}</div>
                <div v-if="item.innerHTML == 'title2'" class="title2">{{ item.name }}</div>
                <div v-if="item.innerHTML == 'title3'" class="title3">{{ item.name }}</div>
                <el-collapse v-if="item.innerHTML == 'All'" v-model="activeNames" @change="handleChange">
                  <el-collapse-item title="添加字段" name="1">
                    <div v-for="(collapse, coIndx) in item.demoList" :key="coIndx" style="padding-right: 10px">
                      <el-input
                        v-if="collapse.innerHTML == 'input'"
                        v-model="collapse.value"
                        :placeholder="collapse.name"
                        class="inptmar"
                      />
                      <el-radio v-if="collapse.innerHTML == 'radio'" v-model="item.radio" :label="collapse.value">
                        {{ collapse.value }}
                      </el-radio>
                    </div>
                    <el-button style="width: 100%" type="primary" @click="adddemoList(item)">+</el-button>
                  </el-collapse-item>
                </el-collapse>
              </div>
            </transition-group>
          </draggable>
        </div>
      </div>
      <div class="dropCenter">
        <div class="col">
          <div class="title">你可以把左边的元素拖到右边</div>
          <draggable
            v-model="arr2"
            group="site"
            animation="300"
            drag-class="dragClass"
            ghost-class="ghostClass"
            chosen-class="chosenClass"
            @start="onStart"
            @end="onEnd"
          >
            <transition-group class="dropminheigth">
              <div v-for="(item, index) in arr2" :key="index" class="Formitem" :class="isRemove ? 'flexForm' : ''">
                <div v-if="item.innerHTML == 'title1'" class="title1">
                  <el-row type="flex" justify="center">
                    <el-input v-model="item.value" v-focus :placeholder="item.name" />
                  </el-row>
                </div>
                <div v-if="item.innerHTML == 'title2'" class="title2">
                  <el-row type="flex" justify="center">
                    <el-input v-model="item.value" v-focus :placeholder="item.name" />
                  </el-row>
                </div>
                <div v-if="item.innerHTML == 'title3'" class="title3">
                  <el-row type="flex" justify="center">
                    <el-input v-model="item.value" v-focus :placeholder="item.name" />
                  </el-row>
                </div>
                <div v-if="item.innerHTML == 'All'" class="inputFlex">
                  <draggable
                    v-model="item.demoList"
                    group="rowDemo"
                    animation="300"
                    drag-class="dragClass"
                    ghost-class="ghostClass"
                    chosen-class="chosenClass"
                    @start="onStart"
                    @change="change2"
                    @end="onEnd"
                  >
                    <transition-group class="inputFlex">
                      <div v-for="(collapse, coIndx) in item.demoList" :key="coIndx" style="padding-right: 10px">
                        <el-input
                          v-if="collapse.innerHTML == 'input'"
                          v-model="collapse.value"
                          :placeholder="collapse.name"
                          class="inptmar"
                        />
                        <el-radio v-if="collapse.innerHTML == 'radio'" v-model="item.radio" :label="collapse.value">
                          {{ collapse.value }}
                        </el-radio>
                      </div>
                    </transition-group>
                  </draggable>
                </div>
                <div v-if="isRemove">
                  <el-button type="danger" icon="el-icon-delete" @click="removeList(index)" />
                </div>
              </div>
            </transition-group>
          </draggable>
        </div>
      </div>

      <div class="rigth-edit">
        <el-button :type="isRemove ? 'success' : 'primary'" @click="isRemove = !isRemove">{{
          isRemove ? '确定' : '修改'
        }}</el-button>
      </div>
    </div>

    <!-- 添加字段弹窗 -->
    <el-dialog
      :visible="isShowDemo"
      title="添加字段"
      width="400px"
      center
      :modal="false"
      :close-on-click-modal="false"
      @close="addFieldCancel"
    >
      <el-form ref="fieldForm" inline label-width="100px" :model="FieldForm" :rules="FieldRule">
        <el-form-item label="类型" prop="type">
          <el-select v-model="FieldForm.type" clearable class="w220" @change="serleChanBtn">
            <el-option :value="1" label="输入框" />
            <el-option :value="2" label="单选框" />
          </el-select>
        </el-form-item>
        <div v-if="FieldForm.type == 1">
          <el-form-item v-for="(indemo, n) in FieldForm.inputList" :key="n" label="字段名" prop="name">
            <el-input v-model="indemo.value" clearable class="w220" />
          </el-form-item>
          <el-form-item label=" ">
            <el-button style="width: 100%" type="primary" @click="addInput">添加输入框</el-button>
          </el-form-item>
        </div>

        <div v-if="FieldForm.type == 2">
          <el-form-item
            v-for="(tarmr, n) in FieldForm.radioList"
            :key="n"
            class="typeRequired"
            :label="'选项' + (n + 1)"
          >
            <el-input v-model="tarmr.value" clearable class="w220" />
          </el-form-item>
          <el-form-item label=" ">
            <el-button style="width: 100%" type="primary" @click="addBtnArea">添加选项</el-button>
          </el-form-item>
        </div>
      </el-form>

      <template #footer>
        <el-row type="flex" justify="center">
          <el-button type="primary" @click="addFieldSave">确定</el-button>
          <el-button @click="addFieldCancel">取消</el-button>
        </el-row>
      </template>
    </el-dialog>
  </el-dialog>
</template>

<script>
// 导入draggable组件
import draggable from 'vuedraggable'
export default {
  name: 'DragAndDropForm',
  components: { draggable },
  props: {
    dragAndDropFormDialog: {
      type: Boolean,
      required: true
    }
  },
  data() {
    return {
      drag: false,
      // 定义要被拖拽对象的数组
      arr1: [
        { name: 'title1', innerHTML: 'title1', value: '' },
        { name: 'title2', innerHTML: 'title2', value: '' },
        { name: 'title3', innerHTML: 'title3', value: '' },
        {
          innerHTML: 'All',
          demoList: []
        }
      ],
      arr2: [
        {
          innerHTML: 'All',
          demoList: [
            {
              name: '输入框',
              innerHTML: 'input',
              value: '测试input1'
            },
            {
              name: '输入框',
              innerHTML: 'input',
              value: '测试input2'
            },
            {
              value: '测试radio1',
              innerHTML: 'radio',
              defaultAr: false
            },
            {
              value: '测试radio2',
              innerHTML: 'radio',
              defaultAr: false
            }
          ]
        },
        {
          innerHTML: 'All',
          demoList: [
            {
              name: '输入框',
              innerHTML: 'input',
              value: '测试input1'
            },
            {
              name: '输入框',
              innerHTML: 'input',
              value: '测试input2'
            },
            {
              value: '测试radio1',
              innerHTML: 'radio',
              defaultAr: false
            },
            {
              value: '测试radio2',
              innerHTML: 'radio',
              defaultAr: false
            }
          ]
        }
      ],
      arr3: [],
      activeNames: ['1'],
      isRemove: false,
      isShowDemo: false,
      FieldForm: {
        demoList: [],
        radioList: [],
        inputList: []
      },
      FieldRule: {},
      letDemoItem: {}
    }
  },
  computed: {}, // 计算属性
  watch: {},
  created() {},
  mounted() {},
  methods: {
    // 开始拖拽事件
    onStart(start) {
      console.log(start)
      this.drag = true
    },
    // 拖拽结束事件
    onEnd(event) {
      // event.item  拖拽的本身
      // event.to      拖拽的目标列表
      // event.from    拖拽之前的列表
      // event.oldIndex    拖拽前的位置
      // event.newIndex    拖拽后的位置
      console.log(event)
      this.drag = false
    },
    // 监听拖拽
    change(event) {
      console.log(event)
      this.arr1 = [
        { name: 'title1', innerHTML: 'title1', value: '' },
        { name: 'title2', innerHTML: 'title2', value: '' },
        { name: 'title3', innerHTML: 'title3', value: '' },
        {
          innerHTML: 'All',
          demoList: []
        }
      ]
    },
    change2(change) {
      console.log(this.arr2)
    },
    adddemoList(item) {
      this.letDemoItem = item
      this.isShowDemo = true
      // item.demoList.push({ name: '输入框', type: 'input', value: '' })
    },
    btnCancel() {
      this.$emit('update:dragAndDropFormDialog', false)
    },
    handleChange(val) {
      console.log(val)
    },
    async removeList(i) {
      try {
        await this.$confirm('是否删除?', { type: 'warning' })
      } catch (error) {
        return
      }
      this.arr2.splice(i, 1)
    },
    serleChanBtn() {
      if (this.FieldForm.type === 1) {
        this.FieldForm = {
          ...this.FieldForm,
          name: '',
          inputList: [
            {
              name: '输入框',
              innerHTML: 'input',
              value: ''
            }
          ],
          radioList: []
        }
      } else if (this.FieldForm.type === 2) {
        this.FieldForm = {
          ...this.FieldForm,
          radioList: [
            {
              value: undefined,
              innerHTML: 'radio',
              defaultAr: false
            }
          ],
          inputList: []
        }
      }
      this.$refs['fieldForm'].resetFields()
    },
    // 添加字段弹层
    addInput() {
      this.FieldForm.inputList.push({ name: '输入框', innerHTML: 'input', value: '' })
    },
    addBtnArea() {
      this.FieldForm.radioList.push({
        value: undefined,
        innerHTML: 'radio',
        defaultAr: false
      })
    },
    // 添加字段保存按钮
    async addFieldSave() {
      try {
        await this.$refs['fieldForm'].validate()
        if (this.FieldForm.type === 2) {
          for (let i = 0; i < this.FieldForm.radioList.length; i++) {
            if (!this.FieldForm.radioList[i].value) {
              return this.$message.warning('请将当前添加的选项填写完整')
            }
          }
        }
        if (this.FieldForm.radioList) {
          this.FieldForm.radioList.forEach((item) => {
            this.letDemoItem.demoList.push(item)
          })
        }
        if (this.FieldForm.inputList) {
          this.FieldForm.inputList.forEach((item) => {
            this.letDemoItem.demoList.push(item)
          })
        }
        this.addFieldCancel()
      } catch (err) {
        console.log(err)
      }
    },
    // 添加字段取消按钮
    addFieldCancel() {
      this.FieldForm = {}
      this.$nextTick(() => {
        this.$refs['fieldForm'].resetFields()
      })
      this.isShowDemo = false
    }
  }
}
</script>

<style lang="scss" scoped>
.dropBox {
  display: flex;
  justify-content: center;
  .dropCenter {
    width: 828px;
  }
}
.inptmar {
  margin: 5px;
}
.title1 {
  font-size: 24px;
}
.title2 {
  font-size: 22px;
}
.title3 {
  font-size: 20px;
}

.backgroundDiv {
  background-color: #eee;
  height: 30px;
  line-height: 30px;
  margin: 2px;
}
/*定义要拖拽元素的样式*/
.ghostClass {
  // background-color: blue !important;
}
.chosenClass {
  // background-color: red !important;
  opacity: 1 !important;
}
.dragClass {
  // background-color: blueviolet !important;
  opacity: 1 !important;
  box-shadow: none !important;
  outline: none !important;
  background-image: none !important;
}
.dropminheigth {
  display: block;
  border: 1px solid #000;
  min-height: 300px;
}
.itxst {
  width: 300px;
}
.title {
  padding: 6px 12px;
}
.col {
  width: 100%;
  border-radius: 5px;
  float: left;
}
.col + .col {
  margin-left: 10px;
}
.item {
  padding: 6px 12px;
  margin: 0px 10px 0px 10px;
  border: solid 1px #eee;
}
.Formitem {
  border-bottom: 1px solid #000;
  background-color: skyblue;
}
.flexForm {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
::v-deep .Formitem {
  .el-input__inner {
    border: 0;
    text-align: center;
  }
  .title1 {
    border-color: aqua;
    .el-input {
      font-size: 24px !important;
    }
  }
  .title2 {
    .el-input {
      font-size: 22px !important;
    }
  }
  .title3 {
    .el-input {
      font-size: 20px !important;
    }
  }
}

.inputFlex {
  display: flex;
  justify-content: space-around;
  align-items: center;
}
.item:hover {
  background-color: #fdfdfd;
  cursor: move;
}
.item + .item {
  border-top: none;
  margin-top: 6px;
}

.rigth-edit {
  margin-left: 10px;
  margin-top: 25px;
}
</style>

配置项

 

group: "name",  // or { name: "...", pull: [true, false, clone], put: [true, false, array] } name相同的组可以互相拖动
  sort: true,  // 内部排序列表
  delay: 0, // 以毫秒为单位定义排序何时开始。
  touchStartThreshold: 0, // px,在取消延迟拖动事件之前,点应该移动多少像素?
  disabled: false, // 如果设置为真,则禁用sortable。
  store: null,  // @see Store
  animation: 150,  // ms, 动画速度运动项目排序时,' 0 ' -没有动画。
  handle: ".my-handle",  // 在列表项中拖动句柄选择器。
  filter: ".ignore-elements",  // 不导致拖拽的选择器(字符串或函数)
  preventOnFilter: true, // 调用“event.preventDefault()”时触发“filter”
  draggable: ".item",  // 指定元素中的哪些项应该是可拖动的。
  ghostClass: "sortable-ghost",  // 设置拖动元素的class的占位符的类名。
  chosenClass: "sortable-chosen",  // 设置被选中的元素的class
  dragClass: "sortable-drag",  //拖动元素的class。
  dataIdAttr: 'data-id',

  forceFallback: false,  // 忽略HTML5的DnD行为,并强制退出。(h5里有个属性也是拖动,这里是为了去掉H5拖动对这个的影响)
  fallbackClass: "sortable-fallback",  // 使用forceFallback时克隆的DOM元素的类名。
  fallbackOnBody: false,  // 将克隆的DOM元素添加到文档的主体中。(默认放在被拖动元素的同级)
  fallbackTolerance: 0, // 用像素指定鼠标在被视为拖拽之前应该移动的距离。

  scroll: true, // or HTMLElement
  scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... }, // if you have custom scrollbar scrollFn may be used for autoscrolling
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
  scrollSpeed: 10, // px

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
draggable是一个Vue.js拖拽组件,可以用于实现在页面中拖拽元素的功能。你可以通过安装npm包vuedraggable来引入这个组件。\[1\]在Vue模板中使用draggable组件的基本用法是将需要拖拽的元素包裹在draggable标签内,并使用v-model指令将数据与拖拽元素进行绑定。例如,你可以使用以下代码实现一个简单的拖拽列表: ```html <template> <div> <!-- 调用组件 --> <draggable element="ul" v-model="list"> <li v-for="item in list">{{item.name}}</li> </draggable> <!-- 输出list数据 --> {{list}} </div> </template> <script> // 引入拖拽组件 import draggable from 'vuedraggable' export default { name: 'demo', components: { //调用组件 draggable, }, data () { return { list:\[ { id: 1, name: 'a' }, { id: 2, name: 'b' }, { id: 3, name: 'c' }, { id: 4, name: 'd' }, { id: 5, name: 'e' }, { id: 6, name: 'f' }, \] } }, } </script> ``` 你也可以通过配置options参数来自定义draggable组件的行为。\[2\]在options对象中,你可以设置动画时间、分组、禁用拖拽功能、拖拽过程中占位元素的class名称、拖拽手柄、排序功能、可拖拽元素的选择器以及不可拖拽元素的选择器等。\[3\] 希望这个回答对你有帮助! #### 引用[.reference_title] - *1* [vue-draggable使用教程](https://blog.csdn.net/rui512777/article/details/129735287)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [vue中使用vue-draggable教程](https://blog.csdn.net/jsmeng626/article/details/131181442)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值