原生 radio 无法点击已选项取消是因为浏览器规范强制同组单选框只能有一个选中态,click 不会触发状态切换;Layui 的 form.render 仅同步样式,需手动在 form.on('radio') 中判断并设置 prop('checked', false),再调用 form.render('radio') 更新 UI。
为什么原生 radio 无法点击已选项取消?
浏览器规范强制 radio 同一组内只能有一个选中态,click 事件触发后若已是 checked,不会触发状态切换。layui 的 form.render('radio') 仅同步 dom 状态到 ui 样式,不改变这个底层行为。所以直接点已选项,form.on('radio') 根本不会触发,更谈不上取消。
form.on('radio') 事件里手动干预 checked 属性
必须绕过默认逻辑,在监听到点击时主动判断并修改状态。关键不是等事件“自然发生”,而是用事件冒泡捕获点击,再决定是否反向操作:
- 监听的是表单域的
radio事件,但实际处理逻辑要写在回调里 - 用
$(data.elem).prop('checked')判断当前是否已选中 - 如果已选中,就用
$(data.elem).prop('checked', false)强制取消 - 最后必须调用
form.render('radio'),否则 UI 不更新(Layui 的样式层和 DOM 层是分离的)
示例代码:
form.on('radio', function(data){
var $elem = $(data.elem);
if ($elem.prop('checked')) {
$elem.prop('checked', false);
form.render('radio');
}
});
避免同组其他 radio 被意外重置
Layui 渲染时会自动给同 name 的 radio 绑定互斥逻辑。如果你在 form.on('radio') 里只改当前项,Layui 内部可能仍认为“该组必须有一个选中”,导致你刚取消的项又被悄悄设回 checked。解决办法是:在取消前,先确保同组其他项全部显式设为 false:
- 获取当前项的
name:var name = $elem.attr('name'); - 清除同名所有项:
$('input[type="radio"][name="' + name + '"]').prop('checked', false); - 再单独对当前项设
false(其实已冗余,但保险) - 最后
form.render('radio')
自定义属性标记点击状态更可靠
依赖 prop('checked') 在某些场景下可能不准(比如表单初始化时 DOM 和 Vue 数据不同步)。更稳妥的方式是用自定义属性如 data-clicked 记录用户是否点过它:
- 初始渲染后遍历所有
radio,根据真实值设data-clicked="true/false" - 在
form.on('radio')回调中读取$(data.elem).data('clicked') - 如果是
true,就取消并设data-clicked=false;否则设true - 每次都要同步更新
prop('checked')和form.render()
这个方式能避开浏览器对 checked 属性的自动修正干扰,尤其适合配合 Vue 或动态数据重载的场景。
form.render('radio') 必须在每次 prop 修改后立即执行,且不能漏掉同组其他项的显式清理**——否则看似取消了,下一帧又自动恢复。











