{ "id": 1, "text": "北京市", "code": 110000, "parentId": 0 }, { "id": 2, "text": "河北省", "code": 220000, "parentId": 0 }, { "id": 3, "text": "河南省", "code": 330000, "parentId": 0 }
id是数据的唯一标识,数据之间的关联关系通过parentId来构建,text,code这种都属于普通的业务字段。如果按这个数据结构,我们查询级联项数据列表的接口就会变得很简单:
//查第一个级联项的列表 /api/cascade?parentId=0 //根据第一个级联项选的值,查第二个级联项的列表 /api/cascade?parentId=1 //根据第二个级联项选的值,查第三个级联项的列表 /api/cascade?parentId=4
这个结构对于后台来说也很好处理,虽然在结构上它们是一种树形的表结构,但是查询都是单层的,所以很好实现。
从前面的查询演示也能够看出,这个结构能够很方便地帮我们把数据查询的接口和参数统一成一个,这对于组件开发来说是一个很方便的事情。我们从后台拿到这个数据结构之后,把每一条数据解析成一个option,如<option value=”北京市” data-param-value=”1”>北京市</option>,这样既能完成数据列表的下拉显示,还能通过select这个表单元素的作用收集到当前级联项所选中的值,最后当级联项发生改变的时候,还能够获取到选中的option,把它上面存储的data-param-value的值作为parentId这个参数,去加载下一个级联项的列表。这也是级联组件数据查询和解析的思路。
但是这里面还需要考虑的是灵活性的问题,在实际的项目中,可能级联组件的数据结构是按id parentId这种类似的关联关系定义的,但是它们的字段不一定是叫id parentId text code,很有可能是别的字段。也就是说:在把数据解析成option的时候,option的text还有value到底用什么字段来解析,以及data-param-value这个属性的用什么字段的值,都是不确定的;还有查询数据时用的参数名称parentId也不能是死的,有的时候如果后台人员先写好了查询接口,用了别的名称,你不可能要求人家去改他的参数名称,因为他那边是需要编译再部署的,相比前端更麻烦一些;还有parentId=0这个0值也是不能固定,因为实际项目中第一层的数据的parentid有可能是空,也有可能是-1。这些东西都得设计成option,一方面提供默认值,同时留给外部根据实际情况来设置,比如本文最终的实现中这个option都是这样定义的:
textField: 'text', //返回的数据中要在<option>元素内显示的字段名称
valueField: 'text', //返回的数据中要设置在<option>元素的value上的字段名称
paramField: 'id', //当调用数据查询接口时,要传递给后台的数据对应的字段名称
paramName: 'parentId', //当调用数据查询接口时,跟在url后面传递数据的参数名
defaultParam: '', //当查询第一个级联项时,传递给后台的值,一般是0,'',或者-1等,表示要查询第上层的数据
2)html结构
根据前面的功能分析的第1条,级联组件的初始html结构有2种:
<ul> <li> <select> <option value="">请选择省份</option> </select> </li> <li> <select> <option value="">请选择城市</option> </select> </li> <li> <select> <option value="">请选择区县</option> </select> </li> </ul>
或
<ul> <li> <select> </select> </li> <li> <select> </select> </li> <li> <select> </select> </li> </ul>
这两个结构唯一的区别就在于是否配置了用作输入提示的option。另外需要注意的是如果需要这个空的option,一定得把value属性设置成空,否则这个空的option在表单提交的时候会把option的提示信息提交到后台。
这两个结构最关键的是select元素,跟ul和li没有任何关系,ul跟li是为了UI而用到的;select元素没有任何语义,不用去标识哪个是省份,哪个是城市,哪个是区县。从功能上来说,一个select代表一个级联项,这些select在哪定义都不重要,我们只要告诉级联组件,它的级联项由哪些select元素构成就行了,唯一需要额外告诉组件的就是这些select元素的先后关系,但是这个通常都是用元素在html中的默认顺序来控制的。这个结构能够帮助我们把组件的功能尽可能地做到表现与行为分离。
3)职责分离和单链表的运用