1 Star 0 Fork 0

Javanx / draglayout

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
This repository doesn't specify license. Without author's permission, this code is only for learning and cannot be used for other purposes.
Clone or Download
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README.md

Vue拖拽组件布局,element ui拖拽组件布局

效果预览

效果解析

1、flex布局成3栏

(1)、左侧定义好固定组件

(2)、中间拖放后的预览效果

(3)、右侧是,点击中间的组件后,可以编辑对应属性

2、利用html5的draggable属性,完成拖动效果

3、vue完成拖放后数据的驱动

4、表单双向绑定,改变组件属性

5、最终数据结构

初始化项目

vue create hello-world

1、安装element-ui

npm i element-ui --save

2、main.js引入

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

3、flex布局 删除掉默认的些许代码

<div class="home">
  <div class="flex">
    <div class="components-group">组件区</div>
    <div class="preview">预览区</div>
    <div class="component-attr">属性编辑区</div>
  </div>
</div>
/** 布局样式 */
.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;
}

这就出来了我们整个的页面结构框架 效果预览

默认组件

咱们是数据驱动的,所有先定义好数据吧。定义好默认组件,并在左侧渲染出来。

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: ''
  }]
  ...
}]
<div class="components-group">
  <div class="components-group-item" v-for="(item, key) in componentsGroup" :key="key">
    <div class="type">{{item.label}}</div>
    <div>
      <div 
      class="components-item"
      v-for="component in item.components" 
      :key="component.id" 
      :data-type="item.type" 
      :data-id="component.id" 
      draggable="true">{{component.label}}</div>
    </div>
  </div>
</div>

样式部分大家自行到git上面看,这里就不一一列出

拖拽

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<lDrags; i+=1) {
      eleDrags[i].onselectstart = function() {
        return false;
      };
      eleDrags[i].ondragstart = function(ev) {
        ev.dataTransfer.effectAllowed = "move";
        ev.dataTransfer.setData("text", ev.target.innerHTML);
        ev.dataTransfer.setDragImage(ev.target, 0, 0);
        eleDrag = ev.target;
        return true;
      };
      eleDrags[i].ondragend = function(ev) {
        ev.dataTransfer.clearData("text");
        eleDrag = null;
        return false
      };
    }
    eleDustbin.ondragover = function(ev) {
      ev.preventDefault();
      return true;
    };

    eleDustbin.ondragenter = function(ev) {
      offsetY = ev.offsetY;
      $('.droptarget').css({
        border: 'none'
      });
      if (ev.target.className.indexOf('droptarget')>-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;
    };
  }
}

这里用到了jquery,感觉还是jquery香啊。

有了数据就简单了,变量数据,根据widgetKey,判断不同的组件渲染不同的element-ui组件即可。详情见git代码。

上方代码还有一个明细控件组,意思是,明细里面可以包含子控件。

Repository Comments ( 0 )

Sign in to post a comment

About

vue拖拽布局 expand collapse
Vue and 3 more languages
Cancel

Releases

No release

Contributors

All

Activities

Load More
can not load any more
1
https://gitee.com/javanx/draglayout.git
git@gitee.com:javanx/draglayout.git
javanx
draglayout
draglayout
master

Search