概述:
写一个简单的控件,只要能够完成其功能就OK了,但是写一个控件库,特别是以类的继承的方式实现的控件库,概念的统一更为重要,本节我试图定义控件的共有属性。
一个控件库有多个控件,各个控件的行为各异,但是控件的各种状态是一致的。如: 选中状态、展开状态、禁用状态、获取焦点等等很多状态,有些状态的概念很好统一,但是有些状态的概念不好统一,容易产生误解,下面一一讲解:
控件状态:
selected 选中状态
选中是控件最常见得状态,分为单选和多选2种选择类型,还需要控制控件是否可以选中,所以我们可以抽象出以下属性:
1. selected 是否选中
2. multipleSelect 是否多选
3. selectable 是否可以选中
active 激活状态
点击控件时,鼠标的 mousedown 和 mouseup之间我们定义一个active事件,这个事件在很多时候非常有用,例如拖拽时,可以定义出以下属性:
1. active : 是否激活
2. activeable : 是否可以激活
hover 鼠标进入状态
鼠标进入控件时,控件需要高亮显示,所以我们定义一个属性:
1. highlighted: 高亮显示
之所以不定义hovered属性的原因是,高亮显示有可能由于其他原因产生
focus 获取焦点状态
当我们使用键盘和鼠标时表单元素或者 设置 tabindex的元素会产生获取焦点的状态,不同的浏览器有不同的表现形式,控件如果要支持键盘事件必须考虑这个状态,由此我们定义出:
1. focused :是否获取焦点
2. focusable:是否可以获取焦点
open打开状态
展开和打开状态这里使用2个名称, expand和open,这是因为我们在实现控件过程中,有2种类型的展开,
1. 一种(expand)是展开的部分属于此控件,例如树控件,展开的子节点也属于树控件;
2. 另一种(open)是,展开的部分不属于控件本身,这种展开是控件的非常态,例如 上下文菜单,菜单项和子菜单之间不存在所属关系。
open 展开状态是说展开的部分不属于控件,看下面的例子:
表格的菜单与表头没有所属关系,但是在操作菜单的过程中,表头要处于 open 的状态,此时使用expand 是不合适的。所以我们这一有以下属性:
1. open : 是否打开
expand 展开状态
展开状态是展开部分属于控件的内容(DOM结构或者子控件),例如多级菜单、树都属于这一种,看下面的例子:
这里的菜单项包含子菜单时,有展开折叠2中状态,因此我们这里有以下属性:
1. collapsible 是否可以折叠
2. collapsed 是否折叠
这里我们使用collapsed的原因是,collapsed的表意更为清晰,便于使用,另一方面,大部分前端控件库的树形结构都是使用collpased属性。
visible 可见状态
显示和隐藏是控件必有得状态,而显示和隐藏又有2种形式:
1. visibility: visible 和 hidden
2. display: block(inline ,inline-block等) 和 none
所以我们这里定义一下属性:
1. visibleMode: 显示的方式
2. visible:是否显示
disabled 禁用状态
禁用控件可以影响控件的大部分其他状态,在禁用状态下,选中、激活、焦点、展开状态都无效。我们这里有属性:
1. disabled
总结:
本节从控件的共有状态出发,整理出控件的常见属性,当然这些属性不是所有控件都有,比如open和collapsed只有在需要展开其他内容时需要。禁用状态会影响其他状态属性的使用。
但是仅仅这些属性,还不足以使我们的控件有完善的功能,而且js的语言特性决定了,属性固有的缺点:
1. 属性改变时不能自动同步跟属性相关的操作
2. 不能监听属性改变
3. 无私有属性,属性容易被覆盖
4. 作用域内的私有变量和原型链上的公有变量各有问题
为了克服以上缺点,接下来我要讲解 控件的事件和属性机制。