vue3引用draggable实现拖拽组件形成form表单

发布时间 2023-04-11 16:17:06作者: 幻影之舞

需求:

  

 

 想要实现这样的一个需求,左边是组件库。中间是展示。拖拉组件到中间就形成一个组件。

刚开始用的form-create,发现不行,又用的form-create-design,但vue3版本的只有element plus库,系统刚开始用的ant-design,而且左边我只需要单行输入框和多行输入框组件就够了,有点用宰牛刀的感觉,而且右侧还不能自定义,看悟空CRM的源码看的头大,他还是用的vue2版本+element ui,只能自己撸一了。

刚开始也是看的vuedraggable文档,https://www.itxst.com/vue-draggable-next/tutorial.html,看了半天没看懂,写了个锤子。

后面找啊找,终于找到了一篇让我搞清了逻辑;https://blog.csdn.net/qq_38686683/article/details/129732531,按这个一步步写最终也出来了,这个文章看一下,改下option,另一篇又看下又改下option。搞到最后啥都没有,空白页一个。啊!差点要疯了

安装

 

npm i -S vuedraggable@next


//导入
import draggable from 'vuedraggable'

 

直接在使用页面导入,因为刚开始文件改了删,删了改,结果一直报错,后面才发现没引入。。。

 

首先建立三个div,分别展示上图的内容

 

Vue3版本里不允许在里面进行for循环了,要用<template #item="{ element }"></template>,element 不能随意修改,就是for循环迭代的item

左侧draggable配置:

<draggable
     :list="leftMenu"
     ghost-class="ghost"
     :force-fallback="true"
     :group="{ name: 'list', pull: 'clone' }"
     :sort="false"
     itemKey="id"
>
   <template #item="{ element }">
         <div class="item move">
               <a-button >
                   <template #icon v-if="element.type === 'Input'"><edit-outlined /></template>
                   <template #icon v-if="element.type === 'Textarea'"><ordered-list-outlined /></template>
                   {{ element.name }}
               </a-button>
         </div>
    </template>
</draggable>

JS

// 左侧组件菜单
const leftMenu = reactive([
    { name: "单行文本", id: 1, type: 'Input' },
    { name: "多行文本", id: 2, type: 'Textarea' },
])

然后这样左侧的菜单就显示了,a-button里是根据name生成不同的icon,icon使用记得引入下,element就看下他的按钮图标怎么用的

import {
    EditOutlined,
    OrderedListOutlined
} from '@ant-design/icons-vue'

 

 

 

 中间draggable:

<draggable
     :list="centerData"
     ghost-class="ghost"
     itemKey="id"
     :force-fallback="true"
     group="list"
     :fallback-class="true"
     :fallback-on-body="true"
     class="draggable"
>
   <template #item="{element}">
          <div class="item move">
              <label class="move">{{ element.name }}</label>
                    <div> <el-input v-model="input" placeholder="请输入" @focus="focusInput(element.name)" v-if="element.type === 'Input'" /></div>
                    <div>
                        <el-input
                             v-model="textarea"
                             :rows="2"
                              type="textarea"
                              @focus="focusInput(element.name)"
                              placeholder="Please input"
                              v-if="element.type === 'Textarea'" />
                    </div>
          </div>
   </template>
</draggable>

template写要展示的组件,然后根据name来控制显隐,左边拖进去的数据就会添加到centerData里,然后遍历判断就可以了,组件少可以这么搞,组件多的建议使用component标签来映射,可以看上边的第二个链接,反正原理现在就弄明白了,右边还在搞,搞完更新

 JS

// 中间数据
const centerData = reactive([])

// 鼠标聚焦输入框时,显示右侧内容
const focusInput = (titleName: string) => {
    rightTitle.value = titleName
}