这里特指下拉框,select。但select有两种形态,由multiple属性决定。在多选形态下,用户按住shift键就能实现多选,但用得不多,主要是占空间。那我们着重说说单选形态及其结构。
下拉框是由多种元素组成,通常我们见过select套着option元素,这中间还能夹一层,optgroup就是对option元素进行分组。option元素里面不能放置其他元素节点,option元素间除了空白或注释节点,也不能放其他东西。
optgroup只是装饰用,对提交数据没有影响,当我们选中某个option元素时,它的selected属性就变成true,之前被选中的元素的selected属性变成false,select元素中selectedIndex的值会变成被选元素的序号(它在所有option元素的位置 )。此外,还有一个鲜为人知的属性selectedOptions,它是对应一个数组,装着被选中的元素,那么它就换成被选中元素。因此DOM操作是一种非常复杂与高消耗的行为,这导致基于虚拟DOM的react库的诞生。减少不必要的DOM操作,就能大幅提高性能。
select的值就是被选中的option元素的值,如果用户定义value属性,那么这值就是option.value,否则就是option的innerHTML,也就是option.text。这当中存在兼容问题,比如有的浏览器会对innerHTML进行两端空白trim操作,有的不会,建议统一使用trim操作。
1 2 3 4 5 6 |
<select name="aaa"> <option value="volvo">Volvo</option> <option value="saab">Saab</option> <option value="opel">Opel</option> <option value="audi">Audi</option> </select> |
option.value的提取方法如下:
1 2 3 4 5 6 7 8 9 10 11 |
//by 司徒正美 var roption = /^<option(?:\s+\w+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?)*\s+value[\s=]/i var valHooks = { "option:get": IEVersion ? function (node) { //在IE11及W3C,如果没有指定value,那么node.value默认为node.text(存在trim作),但IE9-10则是取innerHTML(没trim操作) //specified并不可靠,因此通过分析outerHTML判定用户有没有显示定义value return roption.test(node.outerHTML) ? node.value : node.text.trim() } : function (node) { return node.value } } |
我们在看看如何动态添加option元素。这有两种方式,1是使用W3C的createElement与appendChild,2是使用new Option及options.add方法。
1. 直接使用select.innerHTML
1 2 |
//by 司徒正美 select.innerHTML = ''; |
运行发现标准浏览器如chrome, firefox运行正常,DOM树为
IE(678)全家都呵呵了:
原因在于IE使用innerHTML给select赋值时会根据/^&/(尖括号中间的字母、数字,引号,空格)匹配的字符都干掉,无力吐槽。
2. 使用new Option创建select的options,这是比较推荐的方法。
我们先来看看Option构造器是怎么用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//by 司徒正美 new option(text,value,defaultSelected,selected) /* text:字符串,指定option对象的text属性(即之间的文字) value:字符串,指定option对象的value属性 defaultSelected:布尔值,指定option对象的defaultSelected属性 返回下面selected的默认值 selected:布尔值,指定option对象的selected属性 ture/false 是否选择 http://www.cnblogs.com/SpringSmallGrass/archive/2013/04/14/3019837.html */ |
除了第一个参数,其他都是可选的,相当于
1 2 3 4 5 |
//by 司徒正美 var option = document.createElement("option") option.text = "xxxx" option.value = "aaa" option.selected = true |
再看options.add方法。options是select元素的一个数组属性,里面装着所有option元素。add是其上面的一个方法( IE中它也能出现在select元素上),此方法存在兼容问题。
1 2 3 4 |
var objSelect = document.getElementById('mySelect'); //添加一个选项 objSelect.add(new Option("文本","值")); //这个只能在IE中有效 objSelect.options.add(new Option("text","value")); //这个兼容IE与firefox |
options.add有两种传参方式,第一种要来传入两个元素,第一个是新option元素,第二个是已有的option元素,新元素会插入到旧元素之前。问题出现在第二个参数缺省的情况下: