公司内部管理系统准备改版,最近几天把前端架子搭起来了。在规划底层元素时参考了Bootstrap
和Amaze UI
,一些组件的实现确实很优雅。
比如Amaze UI
的单/复选框。
之前我在模拟单/复选框时,都是很暴力的用 js 解决。
- 绑定点击事件;
- 更改 checked 属性值;
- 切换 class 变更样式。
而打开控制台观察Amaze UI
的单/复选框,发现Elements
状态是无更改的。
更改checked
属性值,并不会影响到标签字面量属性。但是想要切换选中和未选中的样式,如果不是通过切换class
来实现,那便是直接修改DOM
了,而这两种操作在控制台中的都能看到一个状态变化的响应。
那么Amaze
究竟是怎么实现的呢?
我选中一个元素的图标,在Styles
中观察样式变化。直到发现了伪类选择器:checked
和相邻选择器+
,才恍然大悟。
实例
<label for="sex1" class="form-check"> <input type="radio" id="sex1" checked name="sex" value="1"> <span class="check-icons"> <i class="icon icon-check"></i> <i class="icon icon-uncheck"></i> </span> 男 </label> <label for="sex2" class="form-check" > <input type="radio" id="sex2" name="sex" value="0"> <span class="check-icons"> <i class="icon icon-check"></i> <i class="icon icon-uncheck"></i> </span> 女 </label>
|
图标使用的iconfont
,然后添加一些样式,我使用less
作为css
预处理语言。
.form-check { display: inline-block; position: relative; margin-right: 1em; padding-left: 24px; line-height: 28px; cursor: pointer; input { display: none; &:checked+.check-icons { .icon-check { display: inline-block; } .icon-uncheck { display: none; } } } .check-icons { position: absolute; top: 5px; left: 0; width: 18px; height: 18px; text-align: center; .icon { position: absolute; top: 0; left: 0; line-height: 18px; font-size: 18px; } .icon-uncheck { color: #d7d7d7 } .icon-check { color: #4776c8; display: none; } } }
|
- 通过
label:for
属性来触发input:checked
属性值更改。 - 设置相邻选择器,由
:checked
状态变化影响对应的icon显示和隐藏。
兼容性
相邻选择器+
兼容IE7+,而伪类选择器:checked
和label:for
属性兼容IE9+(又是这一道坎…)。
IE7、8的兼容
由选择器的妙用,让我想到了属性选择器[checked]
,兼容性为IE7+。
.ie8 [checked]+.check-icons .icon-check, .ie7 [checked]+.check-icons .icon-check { display: inline-block; } .ie8 [checked]+.check-icons .icon-uncheck, .ie7 [checked]+.check-icons .icon-uncheck { display: none; }
|
我针对IE7、8应用了这些样式,for
属性失去了作用,就需要绑定点击事件来更改checked
值。
做完之后发现并没有什么卵用。
因为属性选择器是针对标签字面量属性启作用,而如input.checked = true;
这种修改方式是不会影响到标签上定义的属性。
这就牵扯到了attribute
和property
的区别。
var ck = document.createElement('input'); ck.type = 'checkbox'; document.body.appendChild(ck); ck.checked = true; ck.getAttribute('checked'); ck.checked = false; ck.setAttribute('checked','checked'); ck.checked
|
- attribute 是 html 标签的属性
- property 是 Dom 标准属性
也许是因为标签自定义属性的存在,这两个属性值是不同步的。
如果想要使[checked]
选择器生效,势必要在点击事件中同步修改attribute
和property
。
实验后发现在IE7、8下正确运行了,对应的icon的display
属性确实变化了,但是肉眼看不到样式更改。
不知道是不是渲染能力差的原因,总是需要在控制台里点击对应的标签后才看得到更改后的样式。
思前思后,既然总归是需要用 js 去兼容,那在IE7、8下还是使用切换class
来控制样式。