这是一篇酝酿了2年的文章,在职的时候团队考虑产品保密不让发技术文章。后来也是一直犹豫,因为涉及到组件设计的问题好像很少有人来说,可能是太简单了。最近做项目时,做到了数据源比较多,而且数据显示的处理也比较复杂。再加上之前做过的这种交互比较多,事件比较杂的这种组件。于是自己稍加总结,虽然简单,也可以着手写一个新的专题类型来讲各种类型组件的设计。那么第一篇就来写一下这篇等了2年的组件设计讲解,我自己起了一个名字叫做“交互密集型”组件。
功能简介
这是一个相册的功能,分为大图模式(图1)和照片墙模式(图2)。
本篇所要分析的主要是进入大图模式的交互:1.用户可以通过点击图2照片墙中的某个图片进入大图模式。2.用户可以在大图模式中右滑图片,来切换大图的显示。3.用户还可以在大图模式中点击顶部的tab菜单,来切换到相应Tab类型的首张图片。
前期设计
相册的大图模式需要支持左右滑动切换图片,双击放大等交互,所以直接用photoswipe这个图片预览的库。
状态变量需要有3个,一个是当前正在显示的图片序号(bigPicIndex)、当前显示的类别编号(TypeIndex)、类别中的子序号(SubIndex)。
在手动滑动图片的时候,需要更新这三个状态,可以通过photoswipe库的beforeChange事件的回调函数swipeMove()来捕获。需要注意,swipeMove()的参数只有一个,就是照片前进和后退的个数。
而点击顶部Tab菜单和照片墙状态下点击图片这两个操作都不是photoswipe库能够捕获的,而且这两个组件直接调用photoswipe库的goTo方法来跳转相应的大图并不方便。所以我们需要让这两个操作变更全局变量bigPicIndex,在大图组件中通过监听bigPicIndex来执行photoswipe库的goTo()函数,切换到相应序号的大图。
但是这里需要注意的是photoswipe库的goTo方法,同样会触发beforeChange事件,来激活swipeMove()函数。
整理事件流
我们首先来看比较特殊的事件流程,就是直接触发swipeMove()的滑动图片。
左右滑动图片确是一开始就触发了swipeMove(),在这里必须要通过图片前进和后退的个数,来计算出新的bigPicIndex,而bigPicIndex的更新在之前的设计中,一定会触发goTo()函数,从而又会回来触发swipeMove()导致异常。如果不需要触发goTo()函数,这里有一个比较hack的方式,就是可以通过加上标志位的方式,执行swipeMove()时,设置一个标志位,监听bigPicIndex的函数判断标志位,如果不要去调用goTo()函数,就直接恢复标志位后返回。
而点击顶部Tab菜单(红色)、点击照片墙状态的小图(黄色)都会通过全局变量bigPicIndex来触发goTo()函数来切换大图,并且最终都会触发swipeMove()函数。因为swipeMove()计算出的全局bigPicIndex与这两个操作更新的bigPicIndex相同所以并不会再去激活bigPicIndex的监听函数,造成重复调用了。
所以经过了标志位的修改,我们的事件流就长成了这样:
本来从bigPicIndex出来的绿线调用goTo()函数已经变成了虚线。并且如果我们需要加上其他修改全部变量的副作用逻辑,例如:当前显示的类别编号(TypeIndex)、类别中的子序号(SubIndex),可以加在swipeMove中,因为三种交互都可以走到这个函数,并且它本身也存在一些计算逻辑。
至此,就完成了一个大图组件的设计流程。