number类型输入框自定义加减按钮功能异常技术求助
修复自定义加减按钮的功能问题
问题说明
你开发的动态表格整体运行正常,但自定义的加减按钮无法实现原生number输入框箭头的功能,点击按钮后数值更新但总计未同步,样式也未按预期显示。
核心问题点
- 内联
onclick代码冗余,事件委托逻辑存在重复调用问题 - 模板中的输入框未使用定义好的
form__number容器和对应类,导致样式失效 - 计算时未处理非数字值,可能出现
NaN错误 - 按钮点击后未确保总计实时更新
修复后的完整代码
HTML
<button id="btn-add-row">Add new row</button> <table id="my-table"> <thead> <tr><th>Quantity</th><th>Price</th><th>Total</th><th></th></tr> </thead> <tbody> </tbody> <tfoot> <tr><td colspan="3"> TOTAL = <input type="text" name="anstotal" value="0" readonly></td><td></td></tr> </tfoot> </table> <template id="template-row"> <tr> <td> <div class="form__number"> <button class="form__number_button form__number_button-minus" type="button" > - </button> <input class="form__number_input-number" type="number" name="qty" value="0" min="0" step="1"> <button type="button" class="form__number_button form__number_button-plus" > + </button> </div> </td> <td> <select name="sel" > <option value="0" disabled selected>Choose a price</option> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </td> <td> <input type="text" name="total" value="0" readonly> </td> <td> <button name="delete-row">Delete</button> </td> </tr> </template>
CSS
/* 补上缺失的CSS变量 */ :root { --size-min-width: 60px; --size: 28px; --color-input-number-border: #ccc; --color-input-number-button-fg: #333; --color-link: #007bff; } table { font-family : Arial, Helvetica, sans-serif; font-size : 14px; background : darkblue; border-collapse : separate; border-spacing : 1px; } th { background-color : aquamarine; padding : .8em .4em; } td { background-color : whitesmoke; padding : .8em .4em; text-align : center; /* 调整为居中适配按钮布局 */ } /* 只有一行时隐藏删除按钮 */ table#my-table tbody tr:only-child button[name="delete-row"] { visibility : hidden; } .form__number { display: flex; position: relative; justify-content: center; flex-direction: row; align-items: center; min-width: var(--size-min-width); width: 100%; border: 1px solid var(--color-input-number-border); border-radius: 3px; } .form__number_input-number { width: var(--size-min-width); height: var(--size); padding: 0; margin: 0; box-sizing: border-box; text-align: center; -moz-appearance: textfield; -webkit-appearance: textfield; appearance: textfield; border: 0; } .form__number_input-number::-webkit-outer-spin-button, .form__number_input-number::-webkit-inner-spin-button { display: none; } .form__number_button { border: 0; background-color: #fff; width: var(--size); height: var(--size); color: var(--color-input-number-button-fg); cursor: pointer; } .form__number_button-minus { border-right: 1px solid var(--color-input-number-border); } .form__number_button-plus { border-left: 1px solid var(--color-input-number-border); } .form__number_button:hover { color: var(--color-link); } .form__number_button:active, .form__number_button:focus { outline: none !important; } .form__number_button::-moz-focus-inner { border: 0; }
JavaScript
const myTable_tBody = document.querySelector('#my-table tbody') , templateRow = document.querySelector('#template-row') , myTable_Total = document.querySelector('#my-table tfoot input[name="anstotal"]') ; AddNewRow(); // 初始化第一行 document.querySelector('#btn-add-row').addEventListener('click', AddNewRow); myTable_tBody.addEventListener('input', setTotals); myTable_tBody.addEventListener('click', e => { const target = e.target; // 处理减号按钮 if (target.matches('.form__number_button-minus')) { const input = target.closest('.form__number').querySelector('input[name="qty"]'); input.stepDown(); setTotals(); } // 处理加号按钮 else if (target.matches('.form__number_button-plus')) { const input = target.closest('.form__number').querySelector('input[name="qty"]'); input.stepUp(); setTotals(); } // 处理删除行按钮 else if (target.matches('button[name="delete-row"]')) { target.closest('tr').remove(); setTotals(); } }); function setTotals() { let Total = 0; [...myTable_tBody.rows].forEach(r => { // 确保数值是有效数字,默认0 const qty = r.querySelector('input[name="qty"]').valueAsNumber || 0; const price = +r.querySelector('select[name="sel"]').value || 0; const inTotal = qty * price; r.querySelector('input[name="total"]').value = inTotal; Total += inTotal; }); myTable_Total.value = Total; } function AddNewRow() { if (myTable_tBody.rows.length < 4) { myTable_tBody.append(document.importNode(templateRow.content, true)); } else { alert("Maximum Passenger per ticket is 4."); } }
修复说明
- 移除内联事件:把按钮的
onclick改成事件委托,统一在父元素处理,代码更整洁易维护 - 完善样式结构:把输入框和按钮放进
form__number容器,补上缺失的CSS变量,调整按钮边框让布局更合理 - 优化事件逻辑:区分不同按钮的处理逻辑,避免重复调用总计计算函数
- 数据安全处理:计算时给数值加默认值0,防止空值或非数字导致的
NaN错误 - 实时同步总计:点击加减按钮后手动调用
setTotals(),确保总计和行内数值实时更新
内容的提问来源于stack exchange,提问作者Bouali Ramzi
相关产品推荐
相关产品推荐

