vue 实现二级菜单拖动穿梭框

项目需求:
1. 需要拖拽效果。
2. 把A菜单的子菜单拖动到B菜单
项目难点:
把A菜单下的子菜单拖动到B菜单,如何判断插入的节点!
问题解析:
1.拖动效果 : 在h5 中drag Api

要让一个元素有支持拖拽,需要在标签上做一个标识。

  <div draggable="true"></div>
元素在拖放过程中触发的事件

1. dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发
2. darg:事件主体是被拖放元素,在正在拖放被拖放元素时触发
3. dragenter:事件主体是目标元素,在被拖放元素进入某元素时触发。
4. dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。
5. dragleave:事件主体是目标元素,在被拖放元素移出目标元素是触发。
6. drop:事件主体是目标元素,在目标元素完全接受被拖放元素时触发。
7. dragend:事件主体是被拖放元素,在整个拖放操作结束时触发

我们需要用到146
1.在拖动得时候 我们要记录一下拖动得是那个元素 所以用到dragstart
2.拖到目标节点,我们要记录一下拖放到那个元素里 所以用dragover
3. 我们把元素拖进去之后,我们要插入,所以用drop

大白话的讲解

去书店买书,1先找到书 2.去找到收银员 3.确认付款

代码
      <div id="index">
        <div class="left">
          <div class="Meum" v-for="item in list" :key="item.id">
            <div class="Ameum" @click="show(item.id,1)">{{item.name}}</div>
            <div class="Bmeum" v-show="item.isShow">
              <div v-for="Z_Item in item.children" :key='Z_Item.id' :draggable="draggable" @dragstart="dragStart($event,Z_Item.id)"> {{ Z_Item.name }} </div>
            </div>
          </div>
        </div>
        <div class="right">
          <div class="Meum" v-for="item in list1" :key="item.id">
            <div class="Ameum" @click="show(item.id,2)" @dragover='dragover($event,item.id)' @drop="drop($event,item.id)">{{item.name}}</div>
            <div class="Bmeum" v-show="item.isShow">
              <div class="cccccc" v-for="Z_Item in item.children" :key='Z_Item.id' :draggable="draggable" >
                <input type="checkbox" @change="onChange(Z_Item)">
                <span>{{ Z_Item.name }}</span>
                <span @click="detele(Z_Item.id)">删除</span>
              </div>
            </div>
          </div>
        </div>
      </div>
      <script>
export default {
  
  name: 'Home',
 
  data(){
    return{
      // isShow:true,
      draggable:true,
      list: [
        {
          name: '一级菜单A',
          isShow:true,
          id: 'a',
          children: [
            {name: '一级菜单A子菜单1-1', id: 'a1-1',state:false},
            {name: '一级菜单A子菜单1-2', id: 'a1-2',state:false},
            {name: '一级菜单A子菜单1-3', id: 'a1-3',state:false}
          ]
        },
        {
          name: '一级菜单B',
          isShow:true,
          id: 'b',
          children: [
            {name: '一级菜单B子菜单2-1', id: 'b2-1',state:false},
            {name: '一级菜单B子菜单2-2', id: 'b2-2',state:false},
            {name: '一级菜单B子菜单3-3', id: 'c2-3',state:false}
          ]
        },
        {
          name: '一级菜单C',
          isShow:true,
          id: 'c',
          children: [
            {name: '一级菜单C子菜单3-1', id: 'c3-1',state:false},
            {name: '一级菜单C子菜单3-2', id: 'c3-2',state:false},
            {name: '一级菜单C子菜单3-3', id: 'c3-3',state:false}
          ]
        }
      ],
      list1: [
        {
          name: '一级菜单A',
          isShow:true,
          id: 'ca',
          children: [
            {name: '一级菜单A子菜单1-1', id: 'a1-1',state:false},
            {name: '一级菜单A子菜单1-2', id: 'a1-2',state:false},
            {name: '一级菜单A子菜单1-3', id: 'a1-3',state:false}
          ]
        },
        {
          name: '一级菜单B',
          isShow:true,
          id: 'bb',
          children: []
        },
      ],
    }
  },
  mounted(){
  },
  methods:{
    dragStart (ev,keyId) {
      this.dom = ev.target
      console.log(keyId)
      //如果左侧没有数据,禁止拖动
      if(this.list1.length<0){
        this.draggable = false
      }else{
        this.draggable = true
      }
    },
    dragover (event) {
      console.log(`拖进来了`)
      if(this.dom != event.target){
      //默认浏览器不支持拖动,如果下面的方法支持拖动
        event.preventDefault()
      }
    },
   show(id,type){
     if(type === 1){
      for(let i=0;i<this.list.length; i++){
        if(this.list[i].id === id){
          this.list[i].isShow = !this.list[i].isShow
        }
      }
     }else{
       for(let i=0;i<this.list1.length; i++){
        if(this.list1[i].id === id){
          this.list1[i].isShow = !this.list1[i].isShow
        }
      }
     }
   },
   drop(ev,keyId){
   //插入节点,不懂的可以单独百度。。。。
    ev.target.nextSibling.appendChild(this.dom)
   },
   onChange(item){
     item.state = !item.state
     console.log(item.state)
   },
   //删除
   detele(id){
     console.log(id)
   }
  }
}
</script>
<style  scoped>
#index{
  display: flex;
}
.left{
  width: 400px;
  height: 500px;
  border: 1px solid #ccc;
}
.Ameum{
  background: #ccc;
  cursor: default;
  text-align: start;
}
.Bmeum{
  background: yellowgreen;
  text-align: start;
  margin-left: 5%;
  cursor: default;
  user-select:none;
}
.right{
  width: 400px;
  height: 500px;
  border: 1px solid #ccc;
  margin-left: 20px;
}
.cccccc{
  display: flex;
  justify-content: space-between;
}
</style>
遇到的坑

咱们现在的页面都是div套div。所以在插入节点的时候,会出现失传已久的事件冒泡。我们需要阻止事件冒泡
event.stopPropagation();
没有具体写代码,只是阐述了一个思路而已,不懂可以留言,小菜鸟,不喜欢勿喷
附上一片优秀的 h5 drag Api 详解https://www.cnblogs.com/wuya16/p/DragApi.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值