> 技术文档 > 用VueDraggable轻松实现拖拽表单和布局搭建:新手也能搞定的低代码方案

用VueDraggable轻松实现拖拽表单和布局搭建:新手也能搞定的低代码方案


一、为什么要用VueDraggable?

如果你做过网页开发,肯定遇到过这样的需求:‌让用户能自己拖拽组件,拼出一个表单或者页面布局‌。比如常见的问卷调查系统、网站后台的页面编辑器等。

如果用原生JavaScript实现拖拽功能,需要处理大量事件监听、坐标计算,代码复杂容易出错。而 ‌VueDraggable‌ 是一个现成的Vue组件,它帮我们封装好了拖拽的核心逻辑,只需要简单配置就能实现以下功能:

  1. 拖拽排序:列表项自由调整顺序
  2. 跨容器拖拽‌:把元素从一个区域拖到另一个区域
  3. 自动同步数据:拖拽后的顺序自动更新到数据中

二、30分钟快速上手

2.1 安装组件

在项目中运行以下命令安装:

# npm管理器npm install vuedraggable# yarn管理器yarn add vuedraggable

  注:不同版本可能有不同的回调方法及回调参数,如非最新版本,需参考官方文档使用,官方文档链接于本文文末。

2.2 基础示例:拖拽列表

    
{{ element.name }}
import draggable from \'vuedraggable\'export default { components: { draggable }, data() { return { // 初始列表数据 myList: [ { id: 1, name: \'苹果\' }, { id: 2, name: \'香蕉\' }, { id: 3, name: \'橘子\' } ] } }}

效果:列表中的水果可以自由拖拽排序,且 myList 数据会自动更新!


三、实战案例:拖拽生成表单

3.1 场景说明

我们要做一个表单设计器:左侧是组件列表(输入框、下拉框等),用户拖拽到右侧画布后,自动在数据库中创建对应字段,同时于右侧生成对应的组件

[左侧组件列表] [右侧画布]▼ 输入框  +-------------------+▼ 下拉框  | 已拖入的组件会 |▼ 单选按钮 | 自动出现在这里 || 并保存到数据库! |+-------------------+

3.2 实现步骤

3.2.1:准备组件库
  

表单组件库

{{ element.icon }} {{ element.label }}
export default { data() { return { // 预定义可拖拽的组件 componentList: [ { type: \'input\', label: \'文本输入框\', icon: \'📝\', fieldName: \'\' // 等待用户填写字段名 }, { type: \'select\', label: \'下拉选择框\', icon: \'🔽\', options: [\'选项1\', \'选项2\'] } ] } }}

说明:group 的 pull: \'clone\' 表示拖拽时复制组件,而不是移动

3.2.2:接收拖拽区域
  

表单设计区

{{ opt }}
export default { data() { return { // 存放用户拖入的组件 droppedComponents: [] } }, methods: { // 拖拽结束时触发 async handleDrop(evt) { const newComponent = this.droppedComponents[evt.newIndex]; // 调用接口保存到数据库 const res = await axios.post(\'/api/save-field\', { type: newComponent.type, fieldName: newComponent.fieldName, options: newComponent.options }); // 给组件绑定数据库生成的ID newComponent.dbId = res.data.id; } }}

3.3 常见问题

Q1:如何避免重复字段名?

在拖拽结束后检查字段名是否已存在:

handleDrop(evt) { const newField = this.droppedComponents[evt.newIndex]; // 检查重复 const isExist = this.droppedComponents.some( item => item.fieldName === newField.fieldName ); if(isExist) { alert(\'字段名不能重复!\'); this.droppedComponents.splice(evt.newIndex, 1); // 移除重复项 return; } // ...保存到数据库}

Q2:如何修改组件属性?

添加双击编辑功能:

 
methods: { showEditPanel(component) { this.$prompt(\'请输入字段名\', \'编辑\', { inputValue: component.fieldName }).then(name => { component.fieldName = name; }); }}

注:本文示例仅使用部分原生组件,如需使用自定义组件或更高级的组件,可于VueDraggable的item插槽中添加更多判断条件即可,使用方式类似。


四、进阶案例:栅格化布局

4.1 目标效果

用户可以通过拖拽调整布局区块的位置和大小,类似下图:

+-----------+-----------+| 区块1 | 区块2 |+-----------+-----------+| 区块3 |+----------------------+

4.2 实现代码

  
{{ element.content }}
export default { data() { return { gridLayout: [ { id: 1, width: 200, height: 100, content: \'区块1\' }, { id: 2, width: 200, height: 100, content: \'区块2\' }, { id: 3, width: 400, height: 200, content: \'区块3\' } ] } }}.grid-container { display: flex; flex-wrap: wrap; gap: 10px;}.grid-item { border: 1px solid #ccc; padding: 20px; cursor: move;}

五、常见问题解答

Q1:拖拽时样式错乱怎么办?

尝试添加以下CSS:

/* 拖拽时的预览效果 */.sortable-chosen { opacity: 0.5;}/* 占位符样式 */.sortable-ghost { background: #f0f0f0;}

Q2:如何限制只能横向拖拽?

设置容器为横向排列:

.draggable-container { display: flex; overflow-x: auto;}

Q3:移动端不生效怎么办?

在组件上添加 forceFallback: true 属性:

VueDraggable常用属性如下:


六、小结

        本文内容均为本人闲时编写,内容不涉及公司内部项目代码,仅提供简单操作思路,无复杂实现流程,可为各位提供VueDraggable使用参考以及快速入门,更多功能可参阅官方文档,本文仅演示实现以上两个功能过程中用到的部分。

进一步学习‌:

  • 官方文档
  • 在线示例合集

        官方文档中给出了大量回调函数及组件参数,具体使用可参考:

vue.draggable中文文档 - itxst.com

如果有其他问题欢迎留言讨论,‌如果本文对你有帮助,请点赞收藏支持作者哦!‌ 😊