layui.rate 的 readonly 参数初始化时生效,但动态设置无效;必须在 render 时传 readonly: true,且需配合数字型 value,并在 choose 回调中手动守卫判断是否只读。

layui.rate 的 readonly 参数到底起不起作用
起作用,但只在初始化时生效;如果后续动态改 readonly 属性(比如用 JS 设置 elem.readOnly = true),UI 和事件不会自动同步——这和表单元素不同,rate 组件不监听 DOM 属性变化。
正确做法是:初始化时就明确传入 readonly: true,而不是后期补设。否则会出现“看起来可点、点下去没反应”或“鼠标悬停有高亮但无法点击”的诡异状态。
- 必须配合
value使用,且value必须是数字类型(4✅,"4"❌) - 若 templet 中用了
lay-value="{{d.score}}",注意后端返回的score字段不能是字符串,否则初始值显示为 0 - 不要混用
readonly: true和event: 'click',后者在只读状态下无意义,还可能干扰移动端 touch 行为
表格中嵌入 rate 后如何让某几行只读
表格场景下,readonly 不是全局开关,而是每行独立控制。你不能只靠初始化参数一劳永逸,因为分页、重载、排序都会重建 DOM,导致所有 rate 实例丢失。
关键动作是:每次 table.render() 的 done 回调里,先销毁旧实例,再按行数据条件决定是否启用只读。
- 用
layui.rate.getRateElem('.js-rate-cell')找到所有评分容器 - 遍历每个容器,读取其绑定的行数据(比如通过
$(this).closest('tr').data('index')或提前存好的data-score) - 对满足条件的行(如
d.status === 'done'),调用layui.rate.render({ elem: this, value: d.score, readonly: true }) - 对可编辑行,用
readonly: false并绑定choose回调提交更新
为什么加了 readonly 还能触发 choose 回调
因为 readonly: true 只禁用鼠标交互,但不阻止 choose 事件被手动触发(比如代码里调 rate.setValue())。如果你在回调里写了 console.log('changed'),它仍会执行——这不是 bug,是设计如此。
真正需要拦截的,是用户操作后的数据同步逻辑。别指望 readonly 自动跳过你的回调函数。
- 在
choose回调开头加守卫判断:if (options.readonly) return; - 或者更稳妥:把是否可编辑的判断逻辑前置到事件绑定环节,只给可编辑行 render rate 实例
- 避免在表格
done里对所有单元格统一 render,再靠readonly拦截——这样容易漏掉异步加载的行
只读评分在移动端的表现问题
安卓 WebView 和部分 iOS Safari 下,readonly: true 的 rate 组件可能仍响应 touchstart,出现短暂闪烁或误触发 focus 样式。这不是 layui 的错,是底层浏览器对 disabled/readonly 的实现差异。
缓解方式不是加 CSS pointer-events: none(会破坏 tab 键导航),而是从交互层隔离:
- 给只读 rate 容器加 class
layui-rate-readonly - 用 CSS 隐藏 hover/focus 状态:
.layui-rate-readonly .layui-rate1:hover, .layui-rate-readonly .layui-rate1:focus { opacity: 1 !important; } - 在
choose回调里直接return,不发请求、不改table.cache - 如果业务强依赖视觉不可点,建议用纯 HTML 星号字符(★☆☆☆☆)替代 rate 组件,避开所有 JS 渲染风险


















