近来, 在业务场景中遇到了这么个事儿。
一个时间规则的设置功能:
通过点击滑动的方式来对某某时段进行编辑
**最终效果如下图: **
当得知这个需求的第一反应,我想到了ElementUI中的date-picker,这不一样样的嘛?
于是,我仅仅用了不到三秒的时间便打开了element的date-picker源码...
洋洋洒洒上千行。
嗯,我放弃了...
不过并不是一无所获,我敏锐地看到了一个再熟悉不过的单词,mousemove! 有了想法,那便开始。
第一步:
首先,需要一个存储所有时间段的数组,每一个时间段都有以下几个属性:
{ start: // 起点 end: // 终点 ...params //剩余的参数,例如给某个时间段设置某些属性值 }
第二步:
要开始点击了
问题来了,在新建一个时间段的时候,第一次点击为新建,而第二次点击则是结束当前时间段的编辑。
这时候,要考虑到一个情况,当第一次点击的时候点击到了已经存在的时间段上,应该是修改操作。
于是,我们可以设置一个flag标识,用来标记当前的点击是属于移动阶段还是结束阶段,并加入了一个判断,判断当前操作的地方是否是已经存在的组。
左键点击代码如下(这里面包含了一些时间段数量的限制以及一些业务方面的东西,可以忽略):
新建的同时,自然而然会遇到插入的问题,也就是当前新建的组可能在任何一个地方。
那么,问题又来了。
怎么判断当前点击的位置是已经存在了的时间段呢?
同时衍生出来的另外两个问题:
(1)如何给当前所有已经选中的目标点加样式
(2)开头和结束的样式是不同的
于是,我建立了三个对象,分别用来存放开始的标记点,结束的标记点,以及所有被选中了的标记点,并且记录下他们所在的组的索引值。
在存放时间段的数组变化的同时,将所有需要用到的标记点对号入座。
将对应的类名添加到各个标记点上。
至此,上面的问题便解决了。
第三步:
重头戏来了,开始滑动。
滑动遇到的第一个问题是,在有了开始点之后,鼠标可以往这一点的前方滑动,也可以往后面滑动,对应的开始和结束的样式也要对应的改变(参考date-picker的表现形式)。
这一点,只要判断时间段结束点比开始点小,则切换两个的数据,并将当前滑动中修改的值改为修改start的值即可。
(这里要注意,默认的滑动修改的值是时间段的end,在这里进行方向的切换)
第四步:
看上图中的check函数,这里是处理在滑动过程中,出现了组与组的覆盖的情况时,要进行的逻辑判断及表现。
这里的大致逻辑为:
(1)当覆盖的时候,当前正在操作的组会将覆盖的组逼退,大家也许能从最开始的预览图中看出一二。
(2)当从覆盖状态变为分离状态的时候,原本被逼退的分组要还原回来(可以看到在点击操作的时候,进行了一次数据保存)。
(3)当确定覆盖之后,分组的状态更新为最后的模样。
至此,选择时间段的功能便大体实现了,无非中间加了一些业务相关的逻辑。
当然,这个组件并没有完全完成。
第五步:
右键会弹出菜单,菜单有删除功能,也可以针对某个时间段设置一些属性。
这些便不在这里记录了,代码也很简单,我的实现方式是在右键点击的同时获取到鼠标的位置,然后弹出菜单。
至于删除,直接对数组进行操作即可。
最后,奉上一些用到了的工具函数:
总结
前前后后,这个组件花了大约两天的时间,特此记录一下。
还有很多可以优化的地方,后续改进。