vue3使用拖拽组件draggable.next的使用教程【保姆级】 | 您所在的位置:网站首页 › vue3文档教程 › vue3使用拖拽组件draggable.next的使用教程【保姆级】 |
环境:vue3+setup语法 首先放官方文档的链接: 中文版本: vue.draggable.next 中文文档 - itxst.com (民间翻译) 英文版本:GitHub - SortableJS/vue.draggable.next: Vue 3 compatible drag-and-drop component based on Sortable.js 因为自己写的过程中,官方文档和网上的资料都非常不明,使用版本各不相同,极易踩坑,自己写完后就总结一下,与诸位共勉。 (一)首先,明确需求:做一个可重复拖拽生成的表格设计器,效果图如下: (二)搭一个基本的可互相拖拽的框架 (1)在终端使用npm命令下载插件 npm i -S vuedraggable@next //导入 import draggable from 'vuedraggable' (2)拖拽插件大致可分为两种使用方式——分组拖拽与单组拖拽单组拖拽为只有一组数据,而拖拽是交换此组数据内部的位置,如下图所示: 而互相拖拽是有两组数据,两组数据可以各自内部换顺序,可以相互拖拽到对方的数组中。 本文需求只用到了互相拖拽,互相拖拽的代码形式如下: //需要克隆的数据,A组 {{ element.name }} //拖拽的结果,B组 {{ element.name }} import draggable from 'vuedraggable' interface type { name: string, id: number } const dragList: type[] = reactive([ { name: "单行文本", id: 1 }, { name: "多行文本", id: 2 }, { name: "计数器", id: 3 }, { name: "单选框组", id: 4 }, ]) const widgetList = reactive([ { name: "多行文本", id: 2 }, ])draggable的一些常用的属性我作了整理,方便根据不同的需求取用,可核对表格填写: 属性 说明 类型 是否必填group 如果是分组拖拽,可通过设置group的name来实现分类。 pull属性代表拖出,put为拖入, :group="{ name :'list',pull : true, put: false }" 代表这个分组与其他name为list的分组可实现分组拖拽,此分组允许拖出,不允许拖入,pull为‘clone’则代表clone模式,pull与put可写可不写,默认值都为true Object / string 否 (分组拖拽时必填) list 绑定的数据 Array 是 sort 是否开启排序功能,默认为true,如果设置为false,它所在组无法排序 Boolean 否 force-fallback 默认false,忽略HTML5的拖拽行为,因为h5里有个属性也是可以拖动,你要自定义ghostClass chosenClass dragClass样式时,建议forceFallback设置为true Boolean 否 (设置ghost-class或drag-class时为必填) ghost-class :ghostClass=“ghostClass” 设置拖动元素的占位符类名,可以将拖动时的元素设置为不同的样式。自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true。 String 否 disabled 是否禁用,默认false Boolean 否 drag-class :drag-class="dragClass"拖动元素的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true Boolean 否 item-key 每个元素唯一的标识,建议使用id itemKey='id',注意,此处无需写成变量形式 String 是 (不填也能运行,但控制台会报警告) 到现在为止,这已经是个互相拖拽的组件了。 (3)如果发现自己写的组件 不能进行拖拽,或者网页上不显示组件 ,或者出现红色报错信息,则检查以下注意点 :group中name是否一致,group为变量,需要 :group =‘{name:'' }’的形式 AB组的元素要实现互相拖拽,元素的数据结构必须完全一致,如果不放心,可以使用interface来定义一个类型诸如 interface itemType { name : string , id:number } AB组绑定的数组是否为响应式,如非响应式,会发生拖拽成功,但不能及时响应的情况,可以用这个方法自检-->先进行拖拽,然后在代码的html部分随便加个东西,然后保存,观察网页上是否显示刚才拖拽的内容,如果出现,那就是数组非响应式的问题。 改正:const arr = reactive([ { name : 'name ' , id : 1 } ]) 在新版vue3中,item插槽是必写的部分,不能使用v-for循环替代。 {{ element.name }}item插槽中只允许有一个子元素,此处有个坑,就是如果有两个子元素,但注释掉了一个,也会报错。哪怕实际上这只有一个子元素。 //正确的 {{ element.name }} //会报错的情况! {{ element.name }}到此为止,已经实现拖拽成功。有些人可能会碰到这个问题————如果B组为空,向B组内拖第一个组件的时候,会出现拖拽困难,只能往拖拽区的最顶部拖才能成功 / 根本无法拖拽成功。 原因:因为B组的draggable渲染时为一个高度为auto的div,当前组如果为空,高度也为0,可拖拽区就会变得很小或不存在。 解决方法:为B组的draggable设计高度,具体代码为添加类名,在css中设置 {{ element.name }} .drag-content { height:500px; //建议是外层嵌套一层div,div固定高,此处再设为100% } (三)将拖拽后的内容替换为element组件/其它指定内容我们发现,拖拽后显示的内容可自由定义,在B组的draggable中设置 此时,我们需要完善dragList的数组结构,来映射拖拽后所形成的不同组件 (在组件少的情况下可以这么做) interface itemType { name: string, id: number, element:string } const dragList: type[] = reactive([ { name: "单行文本", id: 1, element: 'Input' }, { name: "多行文本", id: 2, element: 'Textarea' }, { name: "计数器", id: 3, element: 'InputNumber' }, { name: "单选框组", id: 4, element: 'Radio' }, ]) const widgetList = reactive([ ]) // A组 {{ element.name }} // B组 {{ element.name }}点击控件拖过去,就可以实现如下的效果,如果不想要标题,可以把label部分去掉,其他控件如法炮制即可: 在组件数量少的时候,可以这么做,但数量多时,建议使用component标签来映射 (1)先更改一下文件的结构 (2)写一个公共的函数去返回当前widgets文件夹下的所有文件 // getWidget.ts const gets = {} as any const modules = importa.glob('./*.vue', {eager:true}) for (let each in modules) { const name = (modules[each] as any).default.__name gets[name] = (modules[each] as any).default } console.log(gets); export default gets也可使用globEager方法,编译器会报错:函数已经弃用,不过不影响使用。 此处注意,getWidget.ts文件必须是第一个写入文件夹的,之后再添加vue文件,不然会出现default对象内没有__name属性的情况!!! (3)分别把每个组件的部分写好 // Input.vue const input=ref('') (4)使用component标签映射 {{ element.name }} // 使用函数映射 import draggable from 'vuedraggable' //要注意导入 import getName from './widgets/getWidget' const getWidget = (name: string) => { //写的时候,组件的起名一定要与dragList中的element名字一模一样,不然会映射不上 return getName[name] } (5)最终效果成功实现! |
CopyRight 2018-2019 实验室设备网 版权所有 |