网站首页 > 博客文章 正文
1小时搞定卡片拖拽、自动排列交换位置、拖拽数据存取
来源:https://juejin.im/post/5da53e29e51d457822796ed8
首先演示一下最终效果:
流畅的拖动和交换位置效果,并实时更新数据
支持组件的样式和内容自定义
这是这次系列文章的第一篇,我自己封装了一个用vue实现的拖动卡片组件,并且发布到npm,详细地记录下来了整体制作过程。总共有三篇文章,介绍组件的制作思路和遇到的问题,以及在发布到npm上并下载使用的过程中,发生了什么问题并如何解决。
- 第一篇为组件封装后的使用文档及介绍
- 第二篇为组件的实现思路以及遇到的问题
- 第三篇为将组件打包并上传至npm,如何实现按需加载和下载后使用的问题
这是vue实现的拖动卡片组件,主要实现了:
- 拖动卡片与其他卡片的位置更换,并且其他卡片根据拖动的位置自动顺移
- 拖动的时候可使用鼠标滚动
- 卡片根据数据生成,所有参数和内容都是可以自定义的,方便应用于不同场景
- 不同操作的事件都可获取到,拖动后的位置数据会实时更新
- 可以全局安装和按需加载
如何使用?
下载carddragger
npm install carddragger 复制代码
全局安装
在你vue项目的入口js文件中使用,vue-cli生成的项目一般为main.js文件
import {installCardDragger} from 'carddragger' Vue.use(installCardDragger) 复制代码
按需加载
在组件中直接import
import { cardDragger } from 'carddragger' export default { components:{ cardDragger, } } 复制代码
使用示例
1.基础使用:
<template> <cardDragger :data="cardList"> </cardDragger> </template> <script> export default { data() { return { cardList: [{ positionNum: i, name: "演示卡片"+i, id: "card"+i, }], } } } </script> 复制代码
2.完整示例:
参照源码仓库中的examples
将整个项目clone下来,npm install+npm run serve即可看到完整示例
Props(参数)
属性说明类型默认值data必填,需要传入的卡片数据,具体格式请看下方解释Array-colNum卡片排列的列数Number2cardOutsideWidth卡片外部需要占据的宽度(包括无内容部分)Number590cardOutsideHeight卡片外部需要占据的高度(包括无内容部分)Number380cardInsideWidth卡片的宽度Number560cardInsideHeight卡片的高度Number320detectDistance卡片拖动的时候,会触发交换位置的最小距离Number50
data格式示例:
卡片的内容根据data数据生成或自定义
<template> <div> <cardDragger :data="cardList" :colNum="4" :cardOutsideWidth="300" :cardInsideWidth="260" :cardOutsideHeight="310" :cardInsideHeight="240" /> <!-- 上面的属性都可自定义 --> </div> </template> <script> export default { data(){ return{ cardList: [ { positionNum: 2, name: "测试卡片2", id: "card2", } ] } } } </script> 复制代码
属性说明类型默认值id必填,设置卡片的id作为唯一识别String-positionNum必填,设置卡片位置,从1开始依次递增Number-name选填,设置卡片的标题名称String'默认标题'componentData选填,设置卡片的内容为组件数据,如果此参数具有数据的话,则slot传入的数据失效Array-
Slot(插槽)
首先先介绍一下,卡片内容分为上下两部分:
- 上部分为卡片的标题栏,并且拖拽事件只有点击上部分才触发
- 下部分为卡片的内容
两个部分都是可以进行自定义内容及样式的。若不添加的自定义内容的话,标题栏和内容都是默认背景为白色,显示data中的name。若添加了自定义内容则背景需要自己设置。
标题栏插槽
<cardDragger :data="cardList" > <!-- 在组件中间插入template并设置 v-slot:header="slotProps" header为标题栏的插槽名字,在里面的内容会渲染到你每一个卡片标题栏上 slotProps为从子组件返回的数据,及data数组里面的每一个对象数据--> <template v-slot:header="slotProps"> <!-- 自定义内容 --> <div class="topMenuBox" > <div class="menuTitle" v-if="slotProps.item.name">{{slotProps.item.name}}</div> <div class="menuTitle" v-else> 默认标题 </div> </div> </template> </cardDragger> 复制代码
内容插槽
<cardDragger :data="cardList"> <!-- 与标题栏插槽一致,但需要注意v-slot:content--> <template v-slot:content="slotProps"> <div class="insideData"> {{slotProps.item.name}} </div> </template> </cardDragger> 复制代码
你也可以
<cardDragger :data="cardList"> <!-- 与标题栏插槽一致,但需要注意v-slot:content--> <template v-slot:content="slotProps"> <component :is="slotProps.item.OtherData"></component> <!--这里用到的是vue的动态组件功能动态渲染组件,可传入更多属性至子组件 --> </template> </cardDragger> //省略部分代码,加载你的组件 import exampleChild1 from "./childComponent/exampleChild1" cardList: [ { positionNum: 1, name: "演示卡片1", id: "card1", OtherData:exampleChild1 //OtherData这个是你自己定义的属性,注意不可与componentData属性名字重复 } ] 复制代码
关于内容我做了另外一个判断,你可以将需要的组件放在data的componentData属性里面,内容会自动读取componentData的数据。当然你直接都使用slot就可以忽略这个属性。
import exampleChild1 from "./childComponent/exampleChild1" //省略部分代码 cardList: [ { positionNum: 1, name: "演示卡片1", id: "card1", componentData:exampleChild1 //直接设置即可使用 /*componnetData传入的组件,可传入两个我定义好的Props animationState:{ 类型:Boolean, 功能:首次加载卡片的时候为true,之后为false } itemData:{ 类型:Object, 功能:传入组件数据 } */ } ] //在子组件中使用props即可使用 props:{ animationState:{ type:Boolean, default:true }, itemData:{ type:Object } } 复制代码
渲染优先级:data的componentData > slot > 默认内容
Events(事件)
startDrag
事件作用:
在点击卡片顶部标题栏的时候,触发此函数
事件参数:
startDrag(event,id)
第一个参数event,是点击事件的原生event
第二个参数id,是选中的卡片的id
swicthPosition
作用:
在拖动一个卡片到另外一个卡片的位置的时候,触发此事件
事件参数:
swicthPosition(oldPositon,newPositon,originItem)
第一个参数oldPositon,是卡片原来的位置号码
第二个参数newPositon,是卡片需要交换的位置号码
第三个参数originItem,是卡片交换完成后的数据
finishDrag
事件作用:
拖拽完成松开鼠标后,触发此事件
事件参数:
无
考虑修复的问题
1.data的positionNum出现空缺则会报错,必须从1依次递增。但好像这种场景也不常用,考虑修复ing。
未来计划
- 如果有需要的话我再封装个react版本
- 修改其他需要的参数和进行扩展
觉得这个系列有点意思的话,点个赞支持一下呗!
猜你喜欢
- 2024-10-21 IntersectionObserver: 教你如何实现一个Vue无限滚动的组件
- 2024-10-21 支持服务器端渲染的移动端Vue组件——NutUI
- 2024-10-21 循序渐进Vue+Element 前端应用开发(6)—常规Element界面组件使用
- 2024-10-21 vue动态路由(支持嵌套路由)和动态菜单UI开发框架,无偿源码
- 2024-10-21 如何使用 vue + intro 实现后台管理系统的新手引导
- 2024-10-21 零基础入门vue开发(vue开发步骤)
- 2024-10-21 前端路由与vue-router的基本用法(前端路由实现的两种方式)
- 2024-10-21 Electron-vue客户端开发总结(electron-vue官网)
- 2024-10-21 史上最全 vue-router 讲解 !!!(vue,router)
- 2024-10-21 2021,排名前 15 的 Vue 后台管理模板
你 发表评论:
欢迎- 367℃用AI Agent治理微服务的复杂性问题|QCon
- 358℃初次使用IntelliJ IDEA新建Maven项目
- 355℃手把手教程「JavaWeb」优雅的SpringMvc+Mybatis整合之路
- 351℃Maven技术方案最全手册(mavena)
- 348℃安利Touch Bar 专属应用,让闲置的Touch Bar活跃起来!
- 346℃InfoQ 2024 年趋势报告:架构篇(infoq+2024+年趋势报告:架构篇分析)
- 344℃IntelliJ IDEA 2018版本和2022版本创建 Maven 项目对比
- 342℃从头搭建 IntelliJ IDEA 环境(intellij idea建包)
- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)