# draglayout **Repository Path**: javanx/draglayout ## Basic Information - **Project Name**: draglayout - **Description**: vue拖拽布局 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-09-13 - **Last Updated**: 2021-12-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Vue拖拽组件布局,element ui拖拽组件布局 ![效果预览](http://cdn.javanx.cn/wp-content/themes/lensnews2.2/images/20210913/1.gif) ## 效果解析 1、flex布局成3栏 (1)、左侧定义好固定组件 (2)、中间拖放后的预览效果 (3)、右侧是,点击中间的组件后,可以编辑对应属性 2、利用html5的`draggable`属性,完成拖动效果 3、vue完成拖放后数据的驱动 4、表单双向绑定,改变组件属性 5、最终数据结构 ## 初始化项目 ```bash vue create hello-world ``` 1、安装element-ui ``` npm i element-ui --save ``` 2、main.js引入 ```javascript import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); ``` 3、flex布局 删除掉默认的些许代码 ```html
组件区
预览区
属性编辑区
``` ```css /** 布局样式 */ .home{ height: 100vh; padding: 20px 0; } .flex{ display: flex; justify-content: space-between; } .components-group{ width: 300px; height: 800px; background: #fff; border: 1px solid red; } .preview{ width: 320px; background: #fff; box-shadow: 0px 2px 20px 0px rgb(208 215 222 / 46%); border-radius: 12px; border: 1px solid #edf0f5; padding: 10px; } .component-attr{ width: 300px; height: 800px; background: #fff; border: 1px solid red; } ``` 这就出来了我们整个的页面结构框架 ![效果预览](http://cdn.javanx.cn/wp-content/themes/lensnews2.2/images/20210913/20210913151545.png) ## 默认组件 咱们是数据驱动的,所有先定义好数据吧。定义好默认组件,并在左侧渲染出来。 ``` componentsGroup: [{ type: 1, label: '文本', components: [{ id: 1, widgetKey: 'widget_text_single', label: '单行文本', type: '单行文本', required: true, hint: '请输入', value: '' }] ... }, { type: 10, label: '数值', components: [{ id: 11, widgetKey: 'widget_number', label: '数字', type: '数字', unit: '', // 单位 required: true, hint: '请输入', value: '' }] ... }] ``` ```html
{{item.label}}
{{component.label}}
``` ![](http://cdn.javanx.cn/wp-content/themes/lensnews2.2/images/20210913/20210913152632.png) 样式部分大家自行到git上面看,这里就不一一列出 ## 拖拽 ```javascript mounted(){ this.initDrag() }, methods: { initDrag(){ let vm = this let offsetY = 0 var eleDustbin = $(".preview")[0], eleDrags = $(".components-item"), lDrags = eleDrags.length, eleRemind = $(".dragremind")[0], eleDrag = null; for (var i=0; i-1) { ev.target.style.border = "1px solid red"; } return true; }; eleDustbin.ondrop = function(ev) { $('.droptarget').css({ border: 'none' }); let id = $(eleDrag).data('id'); let type = $(eleDrag).data('type'); if(!id) return false let component = '' if(vm.tabbarActive==1){ vm.componentsGroup.find(item=>{ if(item.type==type){ let components = item.components component = components.find(citem=>citem.id==id) } }) } else { component = vm.componentsGroupGroup.find(item=>item.type==type) } component.widgetNo = moment().valueOf() let components = vm.formData.components var dragitem = ev.target.closest('.form-components-item'); // console.log(dragitem) if(dragitem){ let index = $(dragitem).data('index') let ditem = $(dragitem).data('item') if(ditem.type=='明细'){ if(component.type=='明细'){ Message({ type: 'warning', message: '明细组件中不可以再添加明细组件' }) return } if(!ditem.components){ ditem.components = [] } // component.pno = ditem.widgetNo if(ev.offsetY+5>offsetY){ ditem.components.splice(index, 0, component) }else{ ditem.components.splice(index+1, 0, component) } } else { if(ev.offsetY+5>offsetY){ components.splice(index, 0, component) }else{ components.splice(index+1, 0, component) } } } else { components.push(component) } // components.push(component) components = JSON.parse(JSON.stringify(components)) console.log('components', components) Vue.set(vm.formData, 'components', components) setTimeout(()=>{ vm.initSort() }, 500) return false; }; } } ``` ![](http://cdn.javanx.cn/wp-content/themes/lensnews2.2/images/20210913/2.gif) 这里用到了`jquery`,感觉还是jquery香啊。 有了数据就简单了,变量数据,根据`widgetKey`,判断不同的组件渲染不同的element-ui组件即可。详情见[git](https://gitee.com/javanx/draglayout)代码。 上方代码还有一个明细控件组,意思是,明细里面可以包含子控件。 ![](http://cdn.javanx.cn/wp-content/themes/lensnews2.2/images/20210913/3.gif)