之前有个小需求,需要在页面上把输入框锁死,既不让人改内容,也不让人提交数据。同事随手让 AI 助手 Qwen3.5-Plus 生成了一段 jQuery 代码,看着没什么问题,测试环境一跑就露馅。今天就把这套东西掰开揉碎讲清楚,从需求区分到代码实现,再到实际踩过的坑和扩展场景,一次性说透。
先说结论:jQuery 里让输入框不可输入,从来不是一句disabled就完事的。你得先想清楚“不可输入”到底指什么——是不允许编辑内容,还是不允许获取焦点,还是不允许表单提交携带该字段。不同的业务含义,对应的实现方式完全不同。这篇文章适合前端新手、刚接手老旧项目的人,以及正在用 AI 生成 jQuery 代码但不太敢直接上线的朋友。
1. 场景拆解:你的“不可输入”到底是哪一种需求
1.1 先分清 disabled、readonly 和“看着像禁用”
很多人在写“让输入框不可输入”的时候,第一反应就是disabled。但disabled不是万能的,甚至很多时候是错的选择。我在实际开发里至少遇到过三种不同的需求,它们长得像,处理方式却天差地别。
第一种是真正意义上的“禁用”——字段在当前状态下不允许任何操作,比如只有管理员能改的配置项、已经被审批完成的单据编号。这种场景用disabled最合适,鼠标点进去会自动跳开,键盘输入无效,表单提交时这个字段也不会被带出去。
第二种是“只读”——用户可以看见内容,甚至可以选择复制,但不能修改。比如用户信息详情页里的手机号、订单号。这种需求应该是readonly而不是disabled。区别在于readonly字段仍然会参与表单提交,disabled字段则直接被忽略。如果后端接口要求必须传这个字段,你用了disabled,提交的时候字段直接消失,轻则报错,重则数据错乱。
第三种就比较阴间了——要求“看起来可编辑,实际上不能输入”。比如某些弹窗里需要展示一个默认值,UI 上不能灰掉,要保留输入框的边框和光标感,但用户怎么敲都没反应。这种既不能用disabled(样式会变灰,UI 过不了),也不能用readonly(在某些浏览器里光标仍然会闪)。常规做法是拦截keydown事件,或者干脆用一个<div>模拟输入框。后面我会专门讲这种场景的实现。
1.2 条件禁用的业务场景也给我列明白了
除了上面的静态需求,还有一类是“按条件决定能不能输入”。比如表单里选了“在职”状态,离职日期输入框就禁用;选了“已婚”,配偶姓名输入框才开放。这种动态逻辑在 jQuery 里很常见,尤其老项目里一堆change事件挂着。
我见过的初级写法是每次change事件里硬写一行$('#xxx').attr('disabled', true),然后再在另一个分支里attr('disabled', false)。这样写短期没问题,但在一个多步骤表单里,事件触发顺序一乱,或者遇到 AJAX 回填数据,就会把状态搞乱。正确思路是抽一个函数专门处理字段状态,根据当前表单数据统一计算。
举个例子,一个退款申请表单,只有退款方式选“原路退回”时,银行卡号输入框才可编辑,其他方式一律不可输入。如果你只在change事件里控制,那页面初始化回填数据时,这个输入框的状态就是错的。更好的做法是在读取数据、渲染完成、每次选择方式时都调用同一个“刷新字段状态”的函数,保证任何时候计算出来的结果一致。这个习惯养成之后,很多诡异的“为什么明明选了别的选项,输入框还能编辑”问题会少很多。
1.3 Qwen3.5-Plus 给出的代码为什么不能直接用
同事找 AI 生成的代码大概是这样的:
// AI 生成的典型答案 if (someCondition) { $('#myInput').attr('disabled', true); } else { $('#myInput').removeAttr('disabled'); }单看这一小段,逻辑没错。但放进真实项目里就糟了。第一,attr('disabled', true)和理解中的“设置 disabled 属性”不是一回事,jQuery 的attr方法在设置disabled时会自动转成字符串,某些情况下true会被序列化成"true"字符串,虽然浏览器不挑剔,但代码读起来语义就很怪。第二,这行代码只控制了这一个输入框,如果页面上有十来个输入框要联动,AI 没这个全局视角,它会给你生成十来个重复块。第三,AI 不知道表单提交的现场情况——这个字段是只读还是真正禁用,后端接不接收这个参数,它全不知道,只能给你一个“看起来通用”的答案。
我现在用 Qwen3.5-Plus 这类工具的态度是:拿它当搜索引擎增强版和代码草稿生成器,但拿到手必须自己再过一遍需求。凡是涉及 DOM 状态、表单数据、交互联动的代码,都必须结合项目上下文再动手改。毕竟 AI 看到的是你贴过去的片段,而真实页面里还有几十个其他地方在读写同一个输入框。
2. jQuery 禁用输入框的四类实现与底层差异
2.1 最直接的prop('disabled', true)到底做了什么
如果需求真的是完全禁用,jQuery 环境里最推荐的方式是prop而不是attr。prop操作的是 DOM 属性的 Property,attr操作的是 HTML 属性的 Attribute。对于disabled、checked、selected这类布尔型属性,用prop才能保证在反复切换时状态不会出偏差。
// 推荐写法:禁用 $('#inputId').prop('disabled', true); // 启用 $('#inputId').prop('disabled', false);注意,启用的时候千万不用removeAttr('disabled')。虽然removeAttr确实可以移除属性,但配合prop切换时容易出现状态不一致。比如先prop('disabled', true)再removeAttr('disabled'),在某些 jQuery 版本和浏览器组合下,禁用状态可能残留,输入框仍然点不进去。这不是玄学,是 Property 和 Attribute 的同步机制在捣乱。统一用prop设置true/false,就永远不会有这个问题。
另外要注意,disabled有一个连锁反应:输入框禁用后,点击事件无效,焦点事件无效,连父级表单元素的样式都可能受影响。<fieldset>标签可以一次性禁用里面所有输入组件,但 jQuery 里没人这么用,还是老老实实逐个控制更清晰。
2.2 要保留提交值就选readonly,附带一个光标坑
readonly是最容易被忽略的好东西。它跟disabled最大的区别在于:readonly的输入框内容仍然会随表单提交,而disabled的内容直接不携带。后端接口如果要求必传,用后者的兄弟接口今晚就炸。
// 设为只读 $('#inputId').prop('readonly', true); // 取消只读 $('#inputId').prop('readonly', false);readonly也有自己的脾气。它只对<input>和<textarea>有效,对<select>没用。你给一个下拉框设readonly是无效的,下拉框照样能展开照样能选。想锁住<select>只能靠disabled,或者拦截事件。
还有个容易踩的坑:readonly状态下,输入框仍然可以获得焦点。用户 tab 进去会看到光标在里面闪,但敲键盘没反应。在某些场景下这个体验其实很不错(用户可以选中内容复制),但在另外一些场景下,光标闪动会让人误以为可以输入,结果敲半天没反应。解决方法是额外加一行blur强制让输入框失焦,或者设置tabindex不让它进入焦点序列。具体用哪种,取决于你想要的交互感受。
2.3 拦不住的需求:保留样式又要禁止键盘输入
遇到“不能灰、不能禁用、不能 readonly,但就是不能输入”的需求,我一般会祭出拦截事件的方案。最简单的拦截是阻止keydown:
$('#inputId').on('keydown', function (e) { e.preventDefault(); });这一行代码能让所有键盘操作的输入动作失效,但光标还是能闪,鼠标右键粘贴还能进去。要更彻底一点,还要把paste事件也拦住:
$('#inputId').on('keydown paste drop', function (e) { e.preventDefault(); });用这种方案时要考虑清楚边界——是任何情况下都不能输入,还是“某些条件下不能、某些条件下能”?如果是后者,就要在拦截函数里判断当前状态。我遇到过把这种拦截写成永久事件的,结果后续逻辑要开放输入时,事件没解绑,输入框死活敲不进字,排查半天才发现是这里的问题。所以拦截事件方案,一定要配合状态的切换来动态绑定或解绑,或者写成“判断当前标志位”的形式:
let lockInput = true; // 控制锁定的开关 $('#inputId').on('keydown paste', function (e) { if (lockInput) { e.preventDefault(); } }); // 后续想解锁 lockInput = false;这种写法的好处是控制权握在逻辑手里,不会出现解绑不干净的问题。
2.4 特殊形态的“不可输入”:仿豆包输入框槽位与静态展示
热词里有个“仿豆包输入框槽位”,这个我正好做过类似的。豆包这类 AI 对话产品的输入框,有个很有意思的交互:输入框里可以插入一些“槽位”(slot),这些槽位像选中状态的小卡片,用户可以删除,但不能直接编辑里面的文本。本质上这就是“部分不可输入”的一种形态。
用 jQuery 去模仿的话,核心思路不是把输入框本身禁用,而是将输入框做成一个容器(通常用contenteditable的 div),内部的小卡片区域绑定beforeinput事件拦截,不允许改动卡片文本,只允许删除整个卡片。这里如果直接把整个容器设置成disabled,那用户连文字都没法输,彻底跑偏。
所以遇到“输入框的一部分不可输入”时,不要想着禁用整个输入框,而是要把“输入区”和“受保护内容区”在交互上分开。用 jQuery 做这个挺繁琐的,每个按键的命中判断都要写。但理解了原则,用现代前端框架改造也不难——核心就是别让用户把内容删改到一半。这个场景也提醒我们:接到需求时先画一下交互路径,看清楚用户到底能碰哪里、不能碰哪里。
3. 实操复盘:一次完整的 Qwen3.5-Plus 辅助改造全流程
3.1 需求描述与初始方案
说个我最近真实处理过的需求。一个后台订单管理页面,有个备注输入框,正常情况下用户可以填。当订单状态变成“已完成”之后,所有字段都锁定,备注输入框也不能编辑。后端接口要求:提交订单信息时,备注字段必须携带,即使是空字符串,所以不能直接用disabled。
拿到需求后,我先用 Qwen3.5-Plus 过了一遍思路,它给出的答案是“用 readonly + 控制焦点”。方向是对的,但代码写得太理想化,没考虑页面初始化时回填数据的情况,也没考虑多个状态切换时的事件清理。于是我在它基础上改成了下面的完整方案。
3.2 改造后的完整代码与参数选择逻辑
整个实现分成三步。第一步是状态函数,每到一个新状态就统一刷新所有字段的可用性;第二步是绑定事件;第三步是初始化执行。
// 状态刷新函数:根据订单状态控制备注框 function refreshNoteState(orderStatus) { const $note = $('#orderNote'); if (orderStatus === 'completed') { // 已完成:锁定输入,但保留表单提交 $note.prop('readonly', true); $note.addClass('is-locked'); // 失焦:防止光标闪烁的误导 $note.trigger('blur'); } else { // 其他状态:恢复可编辑 $note.prop('readonly', false); $note.removeClass('is-locked'); } } // 页面初始化 refreshNoteState(initialOrderStatus); // 订单状态切换时 $('#orderStatusSelect').on('change', function () { approveOrderStatus = $(this).val(); refreshNoteState(approveOrderStatus); });为什么用readonly而不是disabled?前面说了,因为后端接口要求必须携带备注字段,disabled会让字段从表单数据里消失,接口直接少参数。为什么额外加blur触发?因为readonly状态下光标可以进去,在“已完成”的详情页里,用户 tab 到备注框,看到光标在闪但敲不进字,体验很差。主动blur一下,用户就知道这里不可编辑。
CSS 部分加了一个锁定态样式,让输入框看起来是只读的感觉,但不至于整体灰掉:
.is-locked { background-color: #f7f7f7; cursor: not-allowed; } .is-locked:focus { outline: none; box-shadow: none; }前端里这种细节很容易被忽略。功能上没错,交互上却多了一个误导性的光标,上线后用户反馈“我点进去想改结果改不了”。加了trigger('blur')之后,这种反馈就消失了。
3.3 谁说禁用就完事了:别忘了表单提交时的边界验证
很多前端新手在完成“锁死输入框”之后,以为万事大吉,结果后端继续报错。因为一个页面里的表单不只有输入框,还有隐藏域、下拉框、文本域。我们锁了一个输入框,但如果提交时带了不该带的东西,或者漏了该带的东西,问题就会转移到接口层。
基于上面的案例,订单提交时的 JS 还要做一层校验兜底:
$('#orderForm').on('submit', function () { const orderStatus = $('#orderStatusSelect').val(); const note = $.trim($('#orderNote').val()); if (orderStatus === 'completed' && note !== '') { // 注意:这里是“需要保留只读内容”,而不是“不能有内容” // 如果想强制清空,建议在这里做,而不是依赖 readonly } });这里要讲的逻辑是:readonly不会阻止用户把既有的值删掉。它是“只读”,不是“不可变”。在某些业务中,只读字段的值不能动,但用户仍然可以选中内容按删除键(虽然删不掉,焦点还在)。如果你需要保证这个字段的值永不变化,最好在提交时再检查一次原始值。就像审批单里的金额字段,前端用readonly锁住,后端接口还是要校验金额与订单一致。前端的一切“不可输入”,都只是用户体验层面的护栏,真正的数据安全一定是在后端再做一遍的。
3.4 遇到动态渲染的内容怎么办:on()事件委托才是正解
前面讲的都是页面静态存在的输入框。但在实际项目里,很多输入框是 AJAX 回填之后才生成的。你要是直接用$('#xxx').on('keydown', ...)这种写法,后续新增的输入框完全不受控制。这时候必须用事件委托。
// 委托给父容器:所有别名输入框按同一规则禁止输入 $(document).on('keydown', '.js-lock-input', function (e) { e.preventDefault(); });事件委托的原理很好理解:事件冒泡到父级,父级再用选择器判断事件源是否匹配。这样不管输入框是页面刚加载时存在的,还是 AJAX 返回后插入的,都能被同一个事件处理函数捕获。这个点尤其适合跟 Qwen3.5-Plus 配合——它生成代码时经常会用“直接给当前元素绑事件”的模式,丢进动态渲染的项目里就无效了。我用了几次之后学乖了,每次都会提醒自己:凡是动态内容,一律用事件委托。另外,委托层的选择器不要写全局$(document),能收敛到某个具体的容器范围就收敛,比如$('#orderForm'),这样能减少无谓的事件冒泡遍历。
3.5 实测对比:三种方案的浏览器表现差异
为了让大家直观感受,我把disabled、readonly、事件拦截三种方案放到同一个页面上做了次简陋的浏览器表现测试。这里直接给结果:
| 方案 | 光标是否可进入 | 键盘是否可输入 | 内容是否参与表单提交 | 样式是否自动变化 |
|---|---|---|---|---|
prop('disabled', true) | 否 | 否 | 否 | 是(变灰) |
prop('readonly', true) | 是 | 否 | 是 | 否 |
| 事件拦截 | 是 | 否 | 是 | 否 |
这个表基本能覆盖大多数业务决策。如果你在意字段必须提交到后端,唯一选择是readonly或事件拦截;如果你完全不想让这个字段出现在提交数据里,选disabled。至于样式变化,可以用 CSS 覆盖,所以选了disabled不代表 UI 一定要灰掉,只是默认它会灰掉而已。
我用 Chrome、Firefox 和 Safari 分别测了下,三者的表现基本一致。唯一有差异的是 IE 时代的旧版本浏览器,readonly对<textarea>的支持会有细微差别。现在 2025 年了,还要兼容那种环境的项目,建议直接用事件拦截方案,反而最可控。
4. 热词背后的相关场景:当“不可输入”不再是一个输入框的事
4.1 第一个子元素:禁用状态影响样式选择器的坑
热搜词里有“jquery 第一个子元素”,这个跟输入框禁用有什么关系?关系很大。很多页面用:first-child选择器来给表单第一项设置特殊样式,比如圆角、间距。当你用disabled锁住第一个输入框之后,它本身没有变灰,但项目里有个全局 CSS 是这么写的:
.form-group:first-child input { background-color: #fafafa; }第一个输入框被禁用后,如果你只在 jQuery 里控制disabled,却忘了对应处理:first-child的样式逻辑,展示上就会出现“明明没编辑过,背景色却像不可用”的混乱。排查这类问题通常要花不少时间,因为代码里看不到任何“异常”,只有视觉上的违和感。
我的经验是:处理禁用状态时,把样式变化跟元素状态绑定,而不是跟位置绑定。比如:“被禁用的输入框统一用.is-disabled类控制样式”,比“第一个子元素特殊处理”要可靠得多。这不是说:first-child不能用,而是说当元素状态会动态变化时,用状态类描述样式,比用位置描述样式更符合实际逻辑。
4.2 表格单元格内容过长:禁用后的悬浮展示与提示处理
另一个热词“jquery datatable 单元格内容过长展示.. 鼠标悬浮展示全部数据”,与输入框禁用也有交集。很多管理后台表格里有一列“备注”,单元格内容可能很长,默认用省略号截断。但你有没有想过,这个单元格内容如果是来自一个只读输入框,用户怎么看到完整内容?
我的处理套路是这样:表格渲染时,超过一定长度的文本截断并加省略号,同时在单元格上挂一个title属性或者自定义悬浮层,鼠标放上去显示完整内容。但如果这个单元格本身是disabled状态的输入框,鼠标根本不会触发悬浮事件——因为disabled控件在某些浏览器里会吞掉鼠标事件。
所以这里有个潜在陷阱:你想把某个表格单元格里的 input 禁用,同时又想让用户悬浮看到完整内容,结果因为禁用了输入框,悬浮提示也失效了。解法有两个。一是不要在<input>上做悬浮,而是包一层<div>,事件挂在 div 上,禁用 input 的交互不影响外层容器的事件触发。二是干脆不渲染真实输入框,直接渲染<span title="完整内容">截断的内容</span>,这样表格区域“看似输入框但其实是纯展示”,完全绕开禁用带来的事件问题。
我实际写过一个版本:
// 渲染备注列时:若为只读态,则展示为 span 而非 input function renderNoteCell(note) { if (!$('#orderForm').hasClass('is-locked')) { return '<input type="text" value="' + note + '" />'; } return '<span class="note-cell" title="' + note + '">' + note.substring(0, 10) + '...</span>'; }这样在锁定状态下,单元格根本不是输入框,也就无所谓“不可输入”了。用户悬浮时看到的是完整数据,提交时则由隐藏域携带真实值。这种思路其实经常用到:与其纠结怎么禁用一个输入框,不如在特定状态下直接换一种渲染形态。灵活度一下子拉满。
4.3 动态输入框组:一组输入框的批量锁定与解锁
有时候要禁用的不是单个输入框,而是一整组动态添加的输入框。比如填写订单明细时,用户可以加减行,每行里有一个数量输入框。提交审核后,所有行的数量都必须锁定。如果行数不定,直接逐个加事件监听是非常蠢的做法,每一行新增都要重新绑定一遍,而且稍不注意旧行的事件就重复绑定了。
我用的是事件委托加 class 状态统一控制:
// 锁定所有行内数量输入框 $('#detailTable').on('keydown keyup change', '.qty-input', function (e) { if ($('#detailTable').hasClass('is-locked')) { e.preventDefault(); return false; } }); // 锁定整表:给表格容器加锁定类 function lockDetailTable() { $('#detailTable').addClass('is-locked'); } // 解锁 function unlockDetailTable() { $('#detailTable').removeClass('is-locked'); }这个方案的核心优势在于:不管表格里新增多少行,只要行内的输入框有.qty-input类,监听就不需要重新绑定。状态由表格容器上的一个类统一控制,也方便在 CSS 里统一调整样式。比如可以写.is-locked .qty-input { background-color: #f5f5f5; }这类规则,不需要每行单独处理。思路就是“以容器为状态中心,用事件委托辐射到所有子元素”,这个模式在 jQuery 项目里非常常用。
4.4 “Unity 输入框长度适配”的跨界联想:禁用并不代表不管长度
热搜词里还有个“unity输入框长度适配”,看着跟 web 前端无关,但道理是相通的。在 Unity 游戏引擎里,UI 输入框组件也有“字符数量限制”“只读模式”等选项。你会发现,即使输入框不可编辑,它的显示长度适配也很重要——字段短了,内容显示不全;字段长了,布局被顶偏。
回到 jQuery,当你把输入框设成readonly后,内容长度对容器宽度的影响依然存在。尤其在做响应式布局时,输入框宽度按父容器百分比设置,禁用状态下的 placeholder 或长文本可能导致换行错位。
处理办法有几个:宽度优先用 CSS 的box-sizing: border-box加上百分比宽度;内容太长时用text-overflow: ellipsis截断;如果输入框本身被禁用且不再需要用户操作,干脆渲染成<div>加同款样式。这样长度适配问题就完全隔离在样式层,不会再跟输入框的原生行为纠缠。
4.5 从 AI 辅助到落地:让 Qwen3.5-Plus 帮你在常见场景里避坑
讲到现在,Qwen3.5-Plus这类 AI 工具在不同场景下能给到哪些参考价值,我可以做个梳理。
- 它能快速生成基础代码骨架,帮你快速验证思路,比如想知道
prop和attr的写法差异,一条提问就能给出对比示例。 - 它能帮你补全边界处理,比如你告诉它“还需要考虑表单提交后字段消失的问题”,它会在生成代码里自动加入隐藏域方案。
- 它能给方案做横向对比,问“readonly 和 disabled 的区别”,它能列出表格,方便快速取舍。
- 它不能替你确认业务场景,比如字段到底要不要提交、UI 到底允不允许灰色、动态事件到底挂在哪个容器上,这些必须结合真实项目判断。
我的使用习惯是:先用自然语言描述场景,让 AI 给一版方案,然后逐个检查方案中的假设是否匹配业务。不匹配的地方就追加提问,直到它给出的代码能落到真实页面里。这种方式比“直接抄一句代码”靠谱得多,也省去自己反复试错的成本。
5. 现场问题排查:禁用输入框后常见的八大故障速查
5.1 故障现象与对应处理思路表
很多人在“禁用输入框”之后会遇到一系列诡异现象,我整理成速查表,方便大家照着排查。
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 禁用后表单提交缺字段 | 用了disabled而不是readonly | 改为readonly,或用隐藏域携带值 |
| 输入框只读后光标还在闪 | readonly保留焦点能力 | 加blur或设置tabindex |
| 动态添加的输入框没被禁用 | 事件没有委托绑定 | 改用$(container).on('keydown', selector, fn) |
| 多个输入框重复绑定事件 | 每行都绑了一次keydown | 用事件委托,避免逐行绑定 |
| 样式没有按预期变灰 | 项目里没有针对禁用态的 CSS | 统一用.is-disabled或[disabled]选择器 |
| 悬浮提示失效 | disabled控件吞掉了鼠标事件 | 外层容器包一层绑定事件,或改用span渲染 |
| AI 生成的代码不生效 | 生成时没有考虑动态渲染和事件委托 | 补全容器选择器,把绑定改为委托 |
| 局部锁定后无法局部解锁 | 解绑事件不彻底 | 统一用标志位切换,而不是反复 on/off |
这张表是我多年踩坑的浓缩版。很多问题不是出在“禁用”这一步,而是出在“禁用之后如何恢复”“如何和动态内容共存”这些外围环节。
5.2 一个非常隐蔽的坑:disabled字段的序列化丢失
前面提过disabled会让字段在表单提交时消失,但很多人没意识到序列化时也一样。如果你提交前用$('#form').serialize()或serializeArray(),disabled的输入框是直接不出现在序列化结果里的。这在 AJAX 提交时特别容易出问题。
举个例子,你需要把备注字段传给后端,但因为某个环节误用了disabled,结果serializeArray()之后数组里压根没有备注这个 key,后端按空字符串处理,或者直接校验失败。排查这样的问题,一看网络请求参数就明白了。所以我的习惯是:
- 凡是“内容必须传给后端”的字段,一律不用
disabled,优先readonly。 - 如果因为某些 UI 原因确实要禁用,就在提交前手动把值塞进一个隐藏域。
- 提交后立刻检查请求 payload,防止字段悄悄失踪。
这种细节属于“看一眼就知道是老手”的经验,希望写出来能帮后来的人省去半小时抓狂时间。
5.3 给新手的检查清单:改完代码要自测的项目
最后一个部分,给所有准备上线的朋友一套自测清单。不要看代码能跑就觉得完事,交互上的细节必须亲自点一遍。
- 鼠标点进输入框,看光标能不能进去。能进去且不允许输入时,考虑是否主动
blur。 - 键盘输入中英文、数字、空格,确认完全没反应。
- 右键粘贴,确认粘贴也不生效。
- 按 Tab 键,看焦点是否会停留在输入框上。如果会,判断这是不是期望行为。
- 提交一次表单,确认该字段在请求参数中是否存在,值是否正确。
- 在锁定状态下尝试用浏览器开发者工具修改
disabled属性,看看是否有提交层面兜底。 - 触发一次状态切换(比如从锁定到解锁),确认输入框完全恢复,事件没有残留。
这套清单看着简单,但真照着跑一遍能揪出不少 CI 时代测不出来的问题。我后来每次做完类似需求,都在浏览器控制台里再把请求参数打一轮,从没翻过车。
我现在的基本动作是:接到“输入框不可输入”的需求,先问自己是哪种“不可输入”,再决定用disabled还是readonly还是事件拦截。写完代码后,配合 AI 工具做一轮审查,但绝不让 AI 替我做业务判断。动态渲染的输入框统一用事件委托,状态切换统一用容器标志位。只要把这几个原则记牢,后续再碰到联动锁定、动态表格、部分槽位不可改这类需求,基本都能快速定位、快速落地。
最后分享一个很实用的小技巧:如果只是想临时观察一个输入框禁用后的表现,不用重新刷新整个页面,在控制台里直接执行$('#inputId').prop('disabled', true),再手动点一点页面,立刻就能看到效果。这个方法在我排查误禁用问题时帮了我很多,比改代码再刷新快得多。