您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
京东低代码平台:水滴物料拖拽至画布方案实践与解析
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
京东低代码平台:水滴物料拖拽至画布方案实践与解析
团座是个云小白
2023-04-07
IP归属:北京
27040浏览
#### 前言 拖拽能力作为低代码平台核心能力之一,对于搭建效率的提升有至关重要的作用。水滴低代码平台的画布区域是基于[react-grid-layout](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Freact-grid-layout%2Freact-grid-layout "https://github.com/react-grid-layout/react-grid-layout")实现,原生具备了画布内的拖拽能力,但对于侧边栏物料等画布以外的元素如何拖拽至画布指定位置则需要自行实现。本文是京东水滴低代码平台关于物料可视化拖拽的一些思路及总结,希望可以对有相关需求的同学提供一些帮助和借鉴。 #### 实现思路\color{#003a8c}{实现思路}实现思路 把一个大象装进冰箱需要3步,那么如果我们想把如下图所示的物料拖到画布指定位置需要几步呢? ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8b3f62534bbb4c5e8b3f35798e95edee~tplv-k3u1fbpfcp-zoom-1.image) **第一步:物料可以被拖动** > 拖放(Drag 和 Drop)是很常见的特性。它指的是您抓取某物并拖入不同的位置。拖放是 HTML5 标准的组成部分:任何元素都是可拖放的。 怎么才可以让页面物料可以拖动呢?很幸运,HTML5已经为我们提供了[拖放能力](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fhtml%2Fhtml5-draganddrop.html "https://www.runoob.com/html/html5-draganddrop.html"),而且使用很方便,只需要在希望被拖动的元素上设置`draggable="true"`即可。这样目标元素就可以进行拖拽了。 **第二步:确定当前拖动物料** 物料是可以拖拽了,但是还需要知道当前拖拽的是什么物料,才能正确添加到画布。拖放能力也提供了一些在拖放的过程中会触发的事件: - **在拖动目标上触发事件(源元素):** - [ondragstart](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fjsref%2Fevent-ondragstart.html "https://www.runoob.com/jsref/event-ondragstart.html") - 用户开始拖动元素时触发 - ondrag - 元素正在拖动时触发 - [ondragend](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fjsref%2Fevent-ondragend.html "https://www.runoob.com/jsref/event-ondragend.html") - 用户完成元素拖动后触发 - **释放目标时触发的事件:** - [ondragenter](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fjsref%2Fevent-ondragenter.html "https://www.runoob.com/jsref/event-ondragenter.html") - 当被鼠标拖动的对象进入其容器范围内时触发此事件 - [ondragover](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fjsref%2Fevent-ondragover.html "https://www.runoob.com/jsref/event-ondragover.html") - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件 - [ondragleave](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fjsref%2Fevent-ondragleave.html "https://www.runoob.com/jsref/event-ondragleave.html") - 当被鼠标拖动的对象离开其容器范围内时触发此事件 - [ondrop](https://link.juejin.cn?target=https%3A%2F%2Fwww.runoob.com%2Fjsref%2Fevent-ondrop.html "https://www.runoob.com/jsref/event-ondrop.html") - 在一个拖动过程中,释放鼠标键时触发此事件 用户开始拖动元素时触发`ondragstart`事件,这个事件很符合要求,当该事件触发,这时就可以通过dispatch将拖拽的物料数据保存到store中。很好,数据保存了,物料也可以拖动,离目标更近了一步。 **第三步:确定物料放入画布区域以及在画布中的位置信息** HTML5的拖放能力提供的事件中有一个当释放目标时触发的事件`ondrop`,但是前面在谈及现状时,其实我们已经提到,目前画布区域是基于react-grid-layout插件实现的,所以不能直接这样使用,这就需要查看react-grid-layout插件的文档是否支持该事件。在文档上面,找到了需要用到的三个字段 ``` // 该字段是判断是否要触发onDrop以及是否允许在画布内拖动 isDroppable: ?boolean = false // 拖拽元素在画布中的占位元素信息,用来计算最终的位置信息 // i -- id // w -- width // h -- height droppingItem?: { i: string, w: number, h: number } // 当释放拖拽目标到画布区域时触发的事件,这里插件帮助我们计算了拖拽元素在画布中最后落下的位置信息 // Calls when an element has been dropped into the grid from outside. onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void 复制代码 ``` 通过`onDrop`字段可以确定拖拽目标落入画布,同时还提供了目标元素在画布中的位置信息,到这里需要的数据和条件都满足了,现在就可以尝试把我们的方案去实现了。 #### 代码实现\color{#003a8c}{代码实现}代码实现 基本思路如下图: ![https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b5023897f62c4210b8246d467a978b1c~tplv-k3u1fbpfcp-zoom-1.image](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1a0d106fb3844f4dbb930a916d115286~tplv-k3u1fbpfcp-zoom-1.image) **第一步:支持拖拽设置** ``` <div className={`droppable-element ${styles.materialGroupItem}`} // 允许拖拽 draggable // unselectable="on" key={key} // 用户开始拖动元素时触发 onDragStart={(e) => { onDragStart(type, key, e) }} <i className={icon} style={{ fontSize: 30 }} /> <div className={styles.materialGroupItemName}>{name}</div> </div> 复制代码 ``` **第二步:保存当前拖拽物料的数据** ``` const onDragStart = (type, key, e) => { ... setMaterial({ type, key: _key, materialData: data, droppingItem: { i, w: layout?.width || 1200, h: layout?.height || 360 }, offsetX: e.nativeEvent.offsetX, offsetY: e.nativeEvent.offsetY }) } 复制代码 ``` **第三步:确定物料放入画布区域并且将其添加到画布** ``` <GridLayout ... onDrop={onDrop} isDroppable droppingItem={material.droppingItem} </GridLayout> 复制代码 ``` ``` /** * Calls when an element has been dropped into the grid from outside */ const onDrop = (layouts, item, e) => { // 拖拽元素在画布中位置 const { x, y } = item const dropInfo = { ...material, x, y, layouts } addMaterial(dropInfo) } 复制代码 ``` 效果展示: ![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3a45d9f6d0e24fd58a0bc9bf3154d805~tplv-k3u1fbpfcp-zoom-1.image) #### 遇到问题\color{#003a8c}{遇到问题}遇到问题 - ##### 问题一 - 问题描述 当把物料拖入画布,布局发生变化react-layout-grid插件就会触发onchange事件;这时会在store中添加一个新的物料,但是如果虚幻一枪,只是在画布中逛了一圈,但是没有放入画布,这时react-layout-grid插件只是删除了占位元素,但是没有触发onchange,导致store中多一条不应该添加的数据。 - 解决方案 当画布在拖拽过程中时,不要去更新store中的物料列表,具体方案就是添加一个标志位,当触发`ondragstart`时设置成`true`;拖拽完成触发`ondragend`设置成`false`;只有物料落入画布,触发`ondrop`时,将更新到物料列表。 - ##### 问题二 - 问题描述 当物料在画布中拖动时,会比较卡顿,非常影响用户体验 - 解决方案 在使用chrome浏览器performance面板对页面进行性能分析时,发现拖拽过程中一直在高频率调用`ondragover`,造成了大量long task执行,导致页面掉帧严重,通过对该事件进行截流,减少调用次数,降低function call消耗时间,避免对页面渲染进行阻塞,将每秒的渲染帧数从36帧提升到53帧 优化前: ![https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d4049e91892242eb96a4490f622ee227~tplv-k3u1fbpfcp-zoom-1.image](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fe797ae0ba8f4f79af01483402851028~tplv-k3u1fbpfcp-zoom-1.image) 优化后: ![https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ca2683d915bc4be6b9d5bc02f95bf39f~tplv-k3u1fbpfcp-zoom-1.image](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d0d57e55c7f4450eadba72f941350723~tplv-k3u1fbpfcp-zoom-1.image) #### 总结\color{#003a8c}{总结}总结 通过HTML5拖拽能力的`draggable`属性以及`ondragstart`事件和`ondrop`事件,并且借助react-grid-layout插件提供的物料位置信息,完成了物料可视化拖拽的实现。需要注意的是对于拖拽这类高频触发的能力,应该多考虑性能问题,避免对用户造成不好的用户体验感。 如果有好的方案或者建议,欢迎提出。同时感谢大家抽出宝贵的时间阅读本篇文章。 作者:京东前端 链接:https://juejin.cn/post/7177697291003363385
非原创文章
上一篇:京东低代码平台:通天塔楼层从设计稿自动生产之路探索
下一篇:MicroApp微前端框架手把手使用指南
团座是个云小白
文章数
24
阅读量
64079
作者其他文章
01
京东探索研究院 | 2023年十大科技趋势
日迈月征,朝暮轮转。这一年里,科技开拓者们,产业同行者们用科技汇聚向上的力量步入了数智时代的 “星辰大海”。数字化是我们创造出来的一个永恒并且充满活力的装置,数智技术正在以前所未有的速度发展,并引发颠覆式的变革。
01
Mysql 和 Redis 数据如何保持一致
Mysql和Redis的关系:Mysql是数据库,用来持久化数据,一定程度上保证数据的可靠性;Redis是用来当缓存,用来提升数据访问的性能
01
【案例分享】如何利用京东云建设高可用业务架构
公有云及私有云客户可通过使用京东云的弹性IAAS、PAAS服务,创建高可用、高弹性、高可扩展、高安全的云上业务环境,提升业务SLA,提升运维自动化水平,降低资源成本及运维成本。有业务迁移上云需求,希望构建云上高可用业务架构的客户或对云上高可用架构规划有兴趣的读者可以一看。
01
剖析一下"抢茅台"脚本底层逻辑
百度了下网上抢茅台的种种手段与方法,发现里面的猫腻还真不少,同时作为风险人也想不断的通过各种技术手段识别发现风险,让羊毛党无处躲藏;也许,竞争对手比你想象中要更加的强大, 今天就带你走近抢茅台的脚本,领略下TA们有趣的灵魂
团座是个云小白
文章数
24
阅读量
64079
作者其他文章
01
京东探索研究院 | 2023年十大科技趋势
01
Mysql 和 Redis 数据如何保持一致
01
【案例分享】如何利用京东云建设高可用业务架构
01
剖析一下"抢茅台"脚本底层逻辑
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号