JS 控件 选中
简介
我们在实现控件:列表、菜单、表格、日期选择等控件时,都需要实现选中效果,常见的选中行为有
- 选中一条记录,清除其他选中(单选)
- 选中一条记录不影响其他记录选中(多选)
分析
当我们去分析这些控件的实现代码时,发现选中的逻辑是几乎完全一样的,那么我们能不能把他们提取出来,这里也有2中方式:
- 继承:提供公用的基类,所有这些控件继承有选中功能的基类
- 扩展:实现一个扩展类,所有需要实现选中效果的类可以去引入这个扩展
扩展和继承的差异在前面的博客里有论述,感兴趣的可以去查看。通过对比我们可以找到使用扩展的很多好处
- 耦合小,在一个控件的实现过程中不考虑选中,仅在扩展中实现。
- 使用灵活,当一个控件的父类不需要有选中效果是,可以在子类上引入选中的扩展。
- 易于理解,这是一种Has A 的关系,就是说选中是控件的一个特性。
选中和取消选中
我们先来分析一下我们实现选中功能需要那些属性(Attr)、方法(method)和事件(event)。
- 点击(或者其他方式)控件的选项,其他方式包括:键盘事件、鼠标悬浮等等。
- 如果当前选项已经选中,那么判断控件是否多选模式
- 如果控件处于多选模式,那么清除控件的选中状态
- 触发清除选中事件
- 如果当前选项未选中,判断控件是否多选模式
- 如果当前选项处于单选状态,清除控件以及选中的选项的状态
- 触发选中操作
从上面选中操作的过程,我们看以看到控件需要以下属性:
selected: 选中状态
selectEvent : 选中的事件(点击、键盘事件或者鼠标悬浮)
multipleSelect: 是否允许多选,决定了选中模式是单选还是多选
触发的事件:
selected: 选项选中事件
unselected:清除选中事件
selectedchange : 选中选项发生改变的事件
这3个事件在什么时候触发我们在下面更为详细的分析,我们从上面的过程中可以抽取出需要定义的方法:
setSelected() : 设置选中
getSelected() : 获取选中的第一项
setSelection() : 多选模式下,可以设置多个选项同时被选中
getSelection(): 获取选中的所有项
clearSelection(): 清除所有选中
事件分析
如果你仔细看过上面的图,会发现,单选和多选模式下选中(selected)、清除选中(unselected)和选中改变(selectedchange)事件的触发机制有很大的差别:
- 单选状态下,选中一项时,需要清理之前选中的项,被清理选中的项不触发unselected事件,也不触发selectedchange事件。
- 多选状态下,选中和清理选中状态时都会触发对应的事件,同时触发selectedchange事件。
我们为什么这样设计?
- 如果单选模式下清理选中状态时也触发unselected事件会如何?
- 也触发selectedchange事件会如何?
如果这样,当我们选中一项时,会
- 触发之前选中项的unselected事件
- 触发之前选中项的selectedchange事件
- 触发当前项的selected事件
- 触发当前项的selectedchange事件
我们在这时候监听 selectedchange 会触发2次,如果保证逻辑正确,必须判断当前项是要选中还是要清除选中,由此带来理解和实现上的复杂性。而在多选状态下:
- 选中一项触发该项的 selected事件,触发该项的unselected事件
- 清除选中一项时触发该项的unselected事件,触发该项的selectedchange事件
所以我们可以把单选操作简单化,单选模式下选中一项那么:
- 触发该项的selected事件,
- 触发该项的selectedchange事件
实现