移动端OTP剪贴板自动填充未触发paste事件,如何触发该事件?
问题
我有一个由6个输入框组成的OTP输入组件,输入内容后会自动跳转至下一个输入框。之前粘贴功能异常,只有第一个输入框会被填充,所以我用jQuery添加了paste事件处理程序来处理粘贴逻辑,代码如下:
$("#otp-container #first").on("paste", function(event){ const clipboardData = event.originalEvent.clipboardData || window.clipboardData; if(clipboardData){ const pastedText = clipboardData.getData('text'); const splittedOTP = pastedText.substring(0, 6).split(""); const otpFieldids = ["#first","#second","#third","#fourth","#fifth","#sixth"]; let isValidOTP = true; for (let i = 0; i < splittedOTP.length; i++) { if (!LoginHelper.prototype.checkIfInputIsNumber(splittedOTP[i].toString())) { isValidOTP = false; break; } } if (isValidOTP) { event.preventDefault(); for (let i = 0; i < otpFieldids.length; i++) { const element = $(`#otp-container ${otpFieldids[i]}`) if (element) { element.val(splittedOTP[i]); } } $(`#otp-container ${otpFieldids[splittedOTP.length-1]}`).select(); } } });
这段代码在用户手动粘贴OTP时能正常工作,但在移动端登录场景下,点击剪贴板自动填充功能时,paste事件未被触发,导致自动填充失效。请问有什么方法可以解决这个问题?
解决方案
1. 监听input事件兜底
移动端自动填充多数情况下不会触发paste事件,但会触发input事件。给第一个OTP输入框添加input事件监听,检测输入内容长度是否超过1,一旦超过就将内容拆分到各个输入框:
$("#otp-container #first").on("input", function(event) { const inputVal = $(this).val(); if (inputVal.length > 1) { const splittedOTP = inputVal.substring(0, 6).split(""); const otpFieldids = ["#first","#second","#third","#fourth","#fifth","#sixth"]; let isValidOTP = true; for (let i = 0; i < splittedOTP.length; i++) { if (!LoginHelper.prototype.checkIfInputIsNumber(splittedOTP[i].toString())) { isValidOTP = false; break; } } if (isValidOTP) { $(this).val(splittedOTP[0]); // 保留第一个字符 for (let i = 1; i < otpFieldids.length; i++) { const element = $(`#otp-container ${otpFieldids[i]}`); element.val(splittedOTP[i] || ""); } // 定位到最后一个有内容的输入框 const lastIndex = Math.min(splittedOTP.length - 1, 5); $(`#otp-container ${otpFieldids[lastIndex]}`).select(); } } });
2. 给所有OTP输入框绑定paste事件
之前仅给第一个输入框绑定了paste事件,移动端自动填充可能会把内容放到其他输入框(比如用户点击第二个输入框后触发自动填充),因此给所有OTP输入框都绑定paste事件:
$("#otp-container input").on("paste", function(event){ const clipboardData = event.originalEvent.clipboardData || window.clipboardData; if(!clipboardData) return; const pastedText = clipboardData.getData('text'); const splittedOTP = pastedText.substring(0, 6).split(""); const otpFieldids = ["#first","#second","#third","#fourth","#fifth","#sixth"]; let isValidOTP = true; for (let i = 0; i < splittedOTP.length; i++) { if (!LoginHelper.prototype.checkIfInputIsNumber(splittedOTP[i].toString())) { isValidOTP = false; break; } } if (isValidOTP) { event.preventDefault(); // 直接覆盖所有输入框内容 for (let i = 0; i < otpFieldids.length; i++) { const element = $(`#otp-container ${otpFieldids[i]}`); element.val(splittedOTP[i] || ""); } $(`#otp-container ${otpFieldids[splittedOTP.length-1]}`).select(); } });
3. 利用change事件补充监听
部分移动端自动填充完成后会触发change事件,给每个OTP输入框添加change事件,当某个输入框内容长度超过1时,触发拆分填充逻辑:
$("#otp-container input").on("change", function() { const inputVal = $(this).val(); if (inputVal.length > 1) { const splittedOTP = inputVal.substring(0, 6).split(""); const otpFieldids = ["#first","#second","#third","#fourth","#fifth","#sixth"]; let isValidOTP = true; for (let i = 0; i < splittedOTP.length; i++) { if (!LoginHelper.prototype.checkIfInputIsNumber(splittedOTP[i].toString())) { isValidOTP = false; break; } } if (isValidOTP) { for (let i = 0; i < otpFieldids.length; i++) { const element = $(`#otp-container ${otpFieldids[i]}`); element.val(splittedOTP[i] || ""); } $(`#otp-container ${otpFieldids[splittedOTP.length-1]}`).select(); } } });
4. 优化输入框HTML属性
给OTP输入框添加合适的HTML属性,帮助移动端识别这是OTP输入,提升自动填充的准确性和事件触发概率:
<input type="text" inputmode="numeric" pattern="[0-9]*" id="first" maxlength="1">
inputmode="numeric"会唤起数字键盘,pattern="[0-9]*"帮助系统识别为数字输入,maxlength="1"确保单个输入框仅能输入一位字符。
内容的提问来源于stack exchange,提问作者NeERAJ TK
相关产品推荐
相关产品推荐

