首页 > 其他分享 >vue 拖拽功能实现

vue 拖拽功能实现

时间:2023-04-22 23:11:59浏览次数:43  
标签:index 功能 vue name 拖动 list item type 拖拽

前言

最新项目里使用到了拖拽的功能,查阅资料后,看到一篇关于拖拽的详细文章:https://www.cnblogs.com/xiaohuochai/p/5886618.html
基于此,记录下 vue 实现拖拽的过程,以下是编写的示例demo效果图:
image

设置拖拽时,需要拖拽的元素要设置 draggable = true 及元素是否可拖动。默认是 draggable = false 不可拖动
实现代码:

<template>
  <div style="margin: 100px;display: flex;flex-direction: column">
    <div style="display: flex;align-items: center;">
<!--      拖动目标-->
      <div v-for="(item,index) in list"
           :key="index" class="list-item"
           :class="[activeTypeIndex === index?'list-item-active':'']"
        @dragenter="typeDragenter($event, item,index)"
        @dragover="typeDragover($event, item,index)"
        @dragleave="typeDragleave"
        @drop="typeDrop"
      >
        <div class="title">{{item.type}}</div>

        <template v-if="item.list&&item.list.length">
          <div style="width: 180px;text-align: center;margin: 10px auto;"
          v-for="(c,i2) in item.list" :key="i2">
            {{c.name}}({{c.en}})
          </div>
        </template>
      </div>
    </div>
    <div>单词分类:把以下的单词放到上面对应的分类里</div>

    <!--    拖动源-->
    <div v-for="(card,i) in cardList"
         :key="i" class="card-item"
         :class="[activeCardIndex === i ? 'active':'']"
         @click="activeCardIndex = i"
         draggable="true"
         @dragstart="cardDragStart($event, card,i)"
         @drag="cardDrag"
         @dragend="cardDragend($event, card,i)"
    >{{card.name}}({{card.en}})</div>
  </div>
</template>

<script>
export default {
  name: "index.vue",
  data(){
    return {
      list:[ // 分类数组
        { type:'A',list:[],isError:false },
        { type:'B',list:[],isError:false },
        { type:'C',list:[],isError:false }
      ],
      activeTypeIndex:null, // 选中的分类下标
      cardList:[ // 单词数组
        {name:'苹果',en:'apple',type:'A'},
        {name:'杨桃',en:'carambola',type:'C'},
        {name:'香蕉',en:'banana',type:'B'},
        {name:'蓝莓',en:'blueberry',type:'B'},
        {name:'牛油果',en:'avocado',type:'A'},
        {name:'樱桃',en:'cherry',type:'C'}
      ],
      activeCardIndex:null, // 选中的单词下标
    }
  },
  methods:{
    cardDragStart(e,item,index){
      this.activeCardIndex = index
      // console.log('cardDragStart--------拖动源:拖动开始时触发----------')
    },
    cardDrag(){
      // console.log('cardDrag-------拖动源:拖动过程中触发-----------')
    },
    cardDragend(e,item,index){
      if(this.activeTypeIndex!=null){
        let typeItem = this.list[this.activeTypeIndex]
        typeItem.list.push(item)
        this.cardList.splice(index,1)
        this.activeTypeIndex = null
      }
      this.activeCardIndex = null
      // console.log('cardDragend-------拖动源:拖动结束触发-----------')
    },
    typeDragenter(e,item,index){
      let cardItem = this.cardList[this.activeCardIndex]

      if(cardItem.type === item.type){
        this.activeTypeIndex = index
      }
      // console.log('typeDragenter-------拖动目标:被拖动元素进入到目标区域时触发-----------')
    },
    typeDragover(e,item,index){
      e = e || event;
      if(e.preventDefault){
        e.preventDefault();

        // 修改光标
        let cardItem = this.cardList[this.activeCardIndex]
        if(cardItem.type !== item.type){
          e.dataTransfer.dropEffect = 'none'; // 禁用拖拽到该区域
        } else{
          e.dataTransfer.dropEffect = 'move';//可拖拽到该区域
        }
      }else{
        e.returnValue = false;
      }
      // console.log('typeDragover-------拖动目标:被拖动元素在目标区域移动时触发-----------')
    },
    typeDragleave(){
      this.activeTypeIndex= null
      // console.log('typeDragleave-------拖动目标:被拖动元素离开目标区域时触发-----------')
    },
    typeDrop(){
      // console.log('typeDragenter-------拖动目标:释放鼠标时触发-----------')
    }
  }
}
</script>

<style lang="scss" scoped>
.list-item{
  border: 1px solid #ccc;
  height: 200px;
  width: 200px;
  display: flex;
  flex-direction: column;
  margin: 10px;
  box-sizing: border-box;
  //transition: all 0.2s;

  .title{
    height: 30px;background: #f5f5f5;text-align: center;line-height: 30px
  }

  &.list-item-active{
    border: 1px solid #0a96ff;
    .title{
      font-weight: bold;
      color: #fff;
      background: #0a96ff;
    }
  }
}
.card-item{
  width: 200px;
  border: 1px solid #ccc;
  padding: 10px;
  margin: 8px;
  text-align: center;
  cursor: pointer;

  &.active{
    border: 1px solid #0a96ff;
    color: #0a96ff;
  }
}
</style>

标签:index,功能,vue,name,拖动,list,item,type,拖拽
From: https://www.cnblogs.com/clownblogs/p/17344402.html

相关文章

  • Vue设置默认加载页面,去掉地址栏#号
     {path:'/',component:Login,//想默认启动的页面},mode:"history"//去掉地址栏的#号 ......
  • 解决vue2.0路由 TypeError: Cannot read property 'matched' of undefined 的错误问题
      找了很久这个问题 解决vue2.0路由TypeError:Cannotreadproperty'matched'ofundefined的错误问题-北桥苏-博客园(cnblogs.com)  解决办法改为   问题解决  没有找到为什么 好像高版本的router没有这个问题 我因为需要降级到了3.1.3 ......
  • Vue Typescript 引入文件接口,就无法使用withDefaults
    就是代码写的不规范报错写法 import{Setting}from'@element-plus/icons-vue' import{defineProps,withDefaults}from'vue' import{PiProject}from'@/types/Project' interfaceProjectCardProps{ project:PiProject } constprops=de......
  • 记录一次艰难的云服务器部署前后端项目springBoot+mybatis和vue(两天解决的前后端跨域
    前言大家好我是歌谣今天继续给大家带来后端java的学习最近刚学习完java的一个增删改查紧接着就是部署项目了代码准备工作前端:vue后端:springboot+mybatis数据库mysql部署后端项目打包找到maven-package-runmavenbuild云服务器上面建立文件mkdir/www/springBoot创建文件......
  • 1.1功能需求
    以下是一个衣服商城系统的用例分析。注册账号用户可以注册成为商城的会员,输入个人信息,包括姓名、性别、联系方式、地址等,以便进行购物和订单管理。浏览商品用户可以浏览商城中的各种商品,包括品牌、类型、颜色、大小、价格等方面的分类,以方便选择心仪的商品。搜索商品......
  • Vue基础知识
    模板语法文本插值(textinterpolation)最基本的数据绑定形式,使用“Mustache”语法即{{...}}<span>Message:{{msg}}</span>{{}}中的值会被替换为相应组件实例中msg属性的值,且会同步地更新原始HTML<p>Message:<spanv-html="msg"></span></p>这里的v-html被称为指令Attrib......
  • RuoYi-Vue 分离版 收获与总结
    https://blog.csdn.net/qq_41965731/article/details/115241184一、常量的定义以下是阿里编码规约   二、图片的base64编码https://blog.csdn.net/duola8789/article/details/78844431概述博客三、在项目启动时将一些数据提交加载到缓存中1.利用@PostConstruct......
  • vue2源码-十二、mixin的使用和原理
    mixin的使用和原理使用:可以通过Vue.mixin来实现逻辑的复用,问题在于数据来源不明确。声明的时候可能对导致命名冲突vue3采用的就是compositionAPI局部混入:varmyMixin={created:function(){this.hello()},methods:{hello:function(){......
  • 毕设-前台功能截图
     首页:显示已有的众筹项目;最上方有导航栏,可实现用户登录注册、管理员入口。  用户登录:只有用户登录了才能查看项目的详情。  支付(沙箱):  ......
  • UE5新功能StateTree源码解析
    StateTree是一种UE5中新增的通用分层状态机,其组合了行为树中的选择器(Selectors)与状态机中的状态(States)和过渡(Transitions)。用户可以创建非常高效、保持灵活且井然有序的逻辑。StateTree包含以树结构布局的状态。状态选择可以在树中的任意位置触发。相比行为树,其组织方式更......