注册

如何编写复杂拖拽组件🐣


b0fc30ecdde74017969d94f2a222e842~tplv-k3u1fbpfcp-zoom-crop-mark:3024:3024:3024:1702.awebp?




阅读本文🦀


1.您将了解到如何让echart做到响应式


2.您将到如何编写复杂的拖拽组件


3.和我一起实现可拖拽组件的增删改查、可编辑、可以拖拽、可排序、可持久化


4.和我一起实现可拖拽组件的删除抖动动画


前言🌵



在业务中得到一个很复杂的需求,需要实现组件中展示ecahrts图表,并且图表可编辑,可排序,大小可调整,还要可持续化,下面就是解决方案啦



正文 🦁


先看效果再一步步实现



技术调研



如何做到可拖拽?自己造轮子?显然不是,当然是站在巨人的肩膀上😁



  1. react-dnd
  2. react-beautiful-dnd
  3. dnd-kit
  4. react-sortable-hoc
  5. react-grid-layout

  • react-dnd

    • 文档齐全
    • github star星数16.4k
    • 维护更新良好,最近一月内有更新维护
    • 学习成本较高
    • 功能中等
    • 移动端兼容情况,良好
    • 示例数量中等
    • 概念较多,使用复杂
    • 组件间能解耦

  • react-beautiful-dnd

    • 文档齐全
    • github star星数24.8k
    • 维护更新良好,最近三月内有更新维护
    • 学习成本较高
    • 使用易度中等
    • 功能丰富
    • 移动端兼容情况,优秀
    • 示例数量丰富
    • 是为垂直和水平列表专门构建的更高级别的抽象,没有提供 react-dnd 提供的广泛功能
    • 外观漂亮,可访问性好,物理感知让人感觉更真实的在移动物体
    • 开发理念上是拖拽,不支持copy/clone

  • dnd-kit

    • 文档齐全
    • github star星数2.8k
    • 维护更新良好,最近一月内有更新维护
    • 学习成本中等
    • 使用易度中等
    • 功能中等
    • 移动端兼容情况,中等
    • 示例数量丰富
    • 未看到copy/clone

  • react-sortable-hoc

    • 文档较少
    • github star星数9.5k
    • 维护更新良好,最近三月内有更新维护
    • 学习成本较低
    • 使用易度较低
    • 功能简单
    • 移动端兼容情况,中等
    • 示例数量中等
    • 不支持拖拽到另一个容器中
    • 未看到copy/clone
    • 主要集中于排序功能,其余拖拽功能不丰富

  • react-grid-layout
    • 文档较少
    • github star 星星15.8k
    • 维护更新比较好,近三个月有更新维护
    • 学习成本比较高
    • 功能复杂
    • 支持拖拽、放大缩小


总结:为了实现我们想要的功能,最终选择react-grid-layout,应为我们想要的就是在网格中实现拖拽、放大缩小、排序等功能


Coding🔥



由于代码量比较大,只讲述一些核心的code



1.先创建基础布局


  • isDraggable 控制是否可拖拽
  • isResizable 控制是否可放大缩小
  • rowHeight控制基础行高
  • layout控制当前gird画布中每个元素的排列顺序
  • onLayoutChange 当布局发生改变后的回调函数

  <ReactGridLayout
isDraggable={edit}
isResizable={edit}
rowHeight={250}
layout={transformLayouts}
onLayoutChange={onLayoutChange}
cols={COLS}
>
{layouts && layouts.map((layout, i) => {
if (!chartList?.some(chartId => chartId === layout.i))
return null

return (<div
key={layout.i}
data-grid={layout}
css={css`width: 100%;
height: 100%`}
>

<Chart
setSpinning={setSpinning}
updateChartList={updateChartList}
edit={edit}
key={layout.i}
chartList={chartList}
chartId={Number(layout.i)}
scenarioId={scenarioId}/>

</div>

)
})}
</ReactGridLayout>


2.如何让grid中的每个echarts图表随着外层item的放大缩小而改变


    const resizeObserver = new ResizeObserver((entries) => {
myChart?.resize()//当dom发生大小改变就重置echart大小
})
resizeObserver.observe(chartContainer.current)//通过resizeObserver观察echart对应的item实例对象

3.如何实现排序的持久化


//通过一下代码可以实现记录edit变量的前后状态
const [edit, setEdit] = useState(false)
const prevEdit = useRef(false)
useEffect(() => {
prevEdit.current = edit
})

 //通过将grid中的每个item的排序位置记录为对象,然后对每个属性进行前后的对比,如果没有改变就不进行任何操作,如果发生了改变就可以
//通过网络IO更新grid中item的位置
useEffect(() => {
if (prevEdit && !edit) {
// 对比前后的layout做diff 判断是否需要更新位置
const diffResult = layouts?.every((layout) => {
const changedLayout = changedLayouts.find((changedLayout) => {
// eslint-disable-next-line eqeqeq
return changedLayout.i == layout.i
})
return changedLayout?.w === layout.w
&& changedLayout?.h === layout.h
&& changedLayout?.x === layout.x
&& changedLayout?.y === layout.y
})
// diffResult为false 证明发生了改变
if (!diffResult) {
//这里就可以做图表发生改变后的操作
//xxxxx
}
}, [edit])

4.如何实现编辑时的抖动动画


.wobble-hor-bottom{
animation:wobble-hor-bottom infinite 1.5s ;
}

@-webkit-keyframes wobble-hor-bottom {
0%,
100% {
-webkit-transform: translateX(0%);
transform: translateX(0%);
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
}
15% {
-webkit-transform: translateX(-10px) rotate(-1deg);
transform: translateX(-10px) rotate(-1deg);
}
30% {
-webkit-transform: translateX(5px) rotate(1deg);
transform: translateX(5px) rotate(1deg);
}
45% {
-webkit-transform: translateX(-5px) rotate(-0.6deg);
transform: translateX(-5px) rotate(-0.6deg);
}
60% {
-webkit-transform: translateX(3px) rotate(0.4deg);
transform: translateX(3px) rotate(0.4deg);
}
75% {
-webkit-transform: translateX(-2px) rotate(-0.2deg);
transform: translateX(-2px) rotate(-0.2deg);
}
}

总结 🍁


本文大致讲解了下如何使用react-grid-layout如何与echart图表结合使用,来完成复杂的拖拽、排序、等功能,但是这个组件实现细节还有很多,本文只能提供一个大值的思路,还是希望能够帮助到大家,给大家提供一个思路,欢迎留言和我讨论,如果你有什么更好的办法实现类似的功能


结束语 🌞



那么我的如何编写复杂拖拽组件🐣就结束了,文章的目的其实很简单,就是对日常工作的总结和输出,输出一些觉得对大家有用的东西,菜不菜不重要,但是热爱🔥,希望大家能够喜欢我的文章,我真的很用心在写,也希望通过文章认识更多志同道合的朋友,如果你也喜欢折腾,欢迎加我好友,一起沙雕,一起进步

0 个评论

要回复文章请先登录注册