You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React格式化SSN输入框无法使用Ctrl+A全选删除,如何修复?

SSN输入框Ctrl+A全选删除功能修复方案

问题根因

  • 按键拦截逻辑未适配Mac系统的Command(Meta)键,也未放行Ctrl/Meta组合类快捷键,导致部分场景下全选操作被拦截
  • 全局渲染后的光标重置逻辑强制取消了所有文本选中状态,Ctrl+A全选后立刻被重置为单个光标,无法触发批量删除

需修改的代码逻辑

  • 调整handleKeyDown按键校验规则:新增Meta键支持,且所有Ctrl/Meta组合快捷键直接放行不拦截
  • 修改useLayoutEffect光标重置逻辑:仅当用户未选中任何文本时才重置光标位置,保留用户主动选中的内容范围

完整修改后代码

import React, { useRef, useState, useLayoutEffect } from "react";

export default function App() {
  const [state, setState] = useState({ phone: "" });
  const cursorPos = useRef(null);
  const inputRef = useRef(null);
  const keyIsDelete = useRef(false);

  const handleChange = (e) => {
    cursorPos.current = e.target.selectionStart;
    let val = e.target.value;
    cursorPos.current -= (
      val.slice(0, cursorPos.current).match(/-/g) || []
    ).length;
    let r = /(\D+)/g,
      first3 = "",
      next3 = "",
      last4 = "";
    val = val.replace(r, "");
    let newValue;
    if (val.length > 0) {
      first3 = val.substr(0, 3);
      next3 = val.substr(3, 2);
      last4 = val.substr(5, 4);
      if (val.length > 5) {
        newValue = first3 + "-" + next3 + "-" + last4;
      } else if (val.length > 3) {
        newValue = first3 + "-" + next3;
      } else {
        newValue = first3;
      }
    } else newValue = val;
    setState({ phone: newValue });
    for (let i = 0; i < cursorPos.current; ++i) {
      if (newValue[i] === "-") {
        ++cursorPos.current;
      }
    }
    if (newValue[cursorPos.current] === "-" && keyIsDelete.current) {
      cursorPos.current++;
    }
  };

  const handleKeyDown = (e) => {
    // 放行所有Ctrl/Meta组合快捷键,适配全选、复制、粘贴等通用操作
    if (e.ctrlKey || e.metaKey) return;
    const allowedKeys = [
      "Control",
      "Meta",
      "Delete",
      "ArrowLeft",
      "ArrowRight",
      "Backspace",
      "Home",
      "End",
      "Enter",
      "Tab"
    ];
    keyIsDelete.current = e.key === "Delete";
    if ("0123456789".includes(e.key) || allowedKeys.includes(e.key)) {
      return;
    }
    e.preventDefault();
  };

  useLayoutEffect(() => {
    if (inputRef.current) {
      // 仅无选中文本时重置光标,保留用户选中状态
      if (inputRef.current.selectionStart === inputRef.current.selectionEnd) {
        inputRef.current.selectionStart = cursorPos.current;
        inputRef.current.selectionEnd = cursorPos.current;
      }
    }
  });

  return (
    <div className="App">
      <input
        ref={inputRef}
        type="text"
        value={state.phone}
        placeholder="SSN"
        onChange={handleChange}
        onKeyDown={handleKeyDown}
      />
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Jon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 16:15:05