如何写一个拖拽日历组件(附源码)

做者简介 Kid 蚂蚁金服·数据体验技术团队css

本文会介绍如何写一个可拖拽日历组件,偏重点在于日历组件的功能挖掘以及对于开发过程的一些思考,编码部分会介绍核心部分的实现。代码在最后也会放出来给你们。react

效果演示

先看下项目最后的实现效果: jquery

running.gif | left | 663x480

前期调研

要作一个可拖拽日历组件,先得去看一圈市场上已有的日历组件作成什么样了。主要是为了收集功能以及避免重复造轮子。我调研了google日历,tower,fullcalendar,teambition,webmail等的日历控件。其中google日历和fullcalendar算是使用感觉比较好的了,如下是他们的使用动图:git

google日历

google.gif | left | 464x372

fullcalendar

QQ20180402-115350-HD.gif | left | 470x397

功能对比

如下是功能细节的对比列表:github

拖拽已有事件
(拖拽默认起始位置)
拖拽已有事件拖拽中效果
(产生遮挡)
左右拖拽事件
(只实现了单方向,而且产生遮挡)
拖拽空白区域新建
事件智能布局
(跨周后事件布局乱了)

从表格的对比能够看到,这几家实现的还算不错的日历组件功能都没有实现全,并且在一些细节上都没作好。能找到的开源的只有fullcalendar,不过他是jquery版本的,并且功能实现的并很差,细节上也有很多错误,因此就打算本身写一个了(终于找到重复造轮子的理由了~)。web

功能

根据以前的调研,一个较好的可拖拽日历控件须要实现的功能:编程

  • 拖拽已有事件
  • 双击添加事件
  • 左右拖拽事件
  • 拖拽空白区域新建事件

除了功能以外,还有用户可用性上的细节打磨:布局

  • 拖拽已有事件的阴影效果
  • 拖拽已有事件拖拽中隐藏
  • 左右拖拽的预览以及阴影效果
  • 事件智能布局,包括堆叠和换行后的冗余清理
  • 拖拽态的处理(偏移量计算以及dragLayer的重写)

编码

需求调研完了进入到编码过程,项目主要基于react和react-dnd。编码的总体步骤包括:测试

  • 绘制日历
  • 根据事件列表绘制事件
  • 事件布局整理,堆叠效果和换行清理
  • 让事件可拖动
  • 让事件可左右拖动
  • 让空白区域可拖动勾选
  • 拖拽阴影处理 细讲的话文章太长,你们看着累,我讲一下关键实现点。

可拖拽区域

image.png | left | 463x253

主要是用了react-dnd的拖拽能力,图里的4种颜色的圈分别对应了4种可拖拽组件的source。google

  • 紫色是事件自己
  • 红色是向左拖拽区域
  • 黑色是向右拖拽区域
  • 绿色是拖拽空白的区域(这个设计最有意思,用拖拽的行为来模拟选中~)

为这4种source分别处理好对应的拖拽事件。为每一个source定义好各自的hover事件能够处理不一样的阴影效果。定义好layer能够处理拖拽时鼠标的预览效果。

事件智能布局

image.png | left | 334x193

事件分类

就是把一天的事件分为如图所示的5种:

  • 1是有前一天,有后一天
  • 2是无前一天,有后一天
  • 3是有前一天,无后一天
  • 4是无前一天,无后一天
  • 5是空白的填充事件

渲染某一天的时候,先渲染1和3这种有前一天的,由于他们有个稳定的index,而后按照优先级渲染事件2,而后是4,填不满空白的渲染事件5。而后将1和2的index传到下一天。这样就能较好的布局了。

新周事件清理

image.png | left | 503x180

如图,检测到新一周开始的时候,我会先清理中间的空白。而后再根据优先级排序事件。

整个开心的代码编码过程结束后,竟然发现本身心里有些拒绝这份代码..为啥写完代码,调试完成后,本身不肯意再回头看了呢。哦,是由于真的写的很差看啊!很差看换句话说就是代码的内在质量差。

质量

软件质量能够分为外在的和内在的。外在质量包括:

  • 可用性
  • 正确性
  • 健壮性
  • ....

外在质量是用户关心的惟一软件特性,我上面一直追求和打磨的其实都属于软件的外在质量。用户是爽的~

可我心里有些拒绝这份刚写的代码的缘由是由于软件的内在质量出了问题,内在质量包括:

  • 可读性(多是最重要的了)
  • 可维护性
  • 可接入性(如今支持自定义form,感受仍是不错的~)
  • ....

写着写着发现代码很差理解了,耐下心细看一下发现:

  • 代码有冗余
  • 子程序命名没有起好
  • 代码结构混乱
  • 瞎定义css名
  • ....

接着干吗,先重构咯~

  • 整理代码结构,抽抽抽,让总体流程清晰
  • 从新思考子程序命名,写注释
  • 思考对外提供的接口,增强可接入性
  • .....

重构完成一波后思考为何内在质量会出现问题呢?

质量上的追求是无穷尽的,不管是内在的仍是外在的。不少技术均可以提高质量:补充测试用例,良好的编程风格,合理的注释,分层抽象,合理的接口...让全部的特性都表现的尽善尽美绝无可能。根据一组互相竞争的目标找出一套解决方案,正是这种状况让软件成为一个真正的工程学科

设计

为何质量会差呢?固然是由于设计的有问题,才会在开发中发现设计不符合而不断调整设计,致使破坏了软件中很是重要的“系统完整性”(人月神话至关推崇的重点)。最终就致使了质量差。

那么为何没有好好设计呢?我估计是由于没有抵挡住“赶忙开始编码”的诱惑! 在思考了如何拖拽已有事件以后我就火烧眉毛的开始编码。没有进行更为详细的设计。其实这个阶段我在大脑里已经隔绝了后续的需求了(为了智力上可管理采起的自我保护吧~)。而在实现完拖拽已有事件以后,我开始思考如何拖拽空白区域新建,发现已有的设计须要调整。而后在想到了一个还不错的点子以后就又开始了编码。设计不完备的循环致使了质量的降低。

其实软件的产生与现实中的食物链同样,需求->设计->编码。一环套一环,越靠近上游出了问题影响面越大。概括就是我每次的设计都是基于并不完整的需求来作的。

应该怎么作呢,应该在最开始的时候尽量的设计全才行。应该加大在初期投入的设计时间。

迭代式开发

可能有朋友看到这里感受,不对啊,设计原本就是“险恶的问题”(也就是必须被解决或者部分解决才能定义的问题)。因此开发过程采用迭代式开发没问题啊。迭代式的好处在于有利于规避风险。不断小成本的尝试来下降失败的风险。因此原本迭代式的开发就必须配备不断的重构来保证质量的。

对于这个问题。我以为应该看项目的规模。看咱们脑海中可控的复杂度。可能更好的方式是进行原型的开发进行试验,试验发现可能以后马上从新总体设计,而后再编码,这样的成本会更小些。

就是在初次迭代进行了一些难点的验证以后,进行总体设计,这样能够减小迭代式开发后必不可少的重构环节,减小总体的开发成本,也提升了项目的质量。

总结

本文分享了可拖拽日历组件的实现过程,编码细节以及对于总体开发的思考。之因此会探讨对于开发的思考是由于各类方法论都被用于大小不一样的项目,对于小项目,方法论的应用显得很不经意且趋于本能。若是咱们有选择的使用一些方法论的话是可以减小开发时间以及提高产品质量的。最后附上代码的传送门,具体的接入使用能够看下项目的README,仍是有至关多缺陷的,欢迎提PR~

对咱们团队感兴趣的能够关注专栏,关注github或者发送简历至'tao.qit####alibaba-inc.com'.replace('####', '@'),欢迎有志之士加入~

原文地址:github.com/ProtoTeam/b…

相关文章
相关标签/搜索