React-如何将电话号码格式化为用户类型

发布于 2021-01-31 22:43:08

我需要将10位数字的字符串格式设置为以下格式:’(123)456-7890’。但是,我需要在用户输入时发生这种情况。因此,如果用户仅输入了3位数字,则输入应显示:“(123)”。如果他们输入了5位数字,则输入内容应显示为:“(123)45”

使用我当前的代码,仅在输入第10个字符后才进行格式化。我希望它能从第三个字符开始对其进行格式化。

const phoneRegex = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/

const handleInput = (value) => {
  return (
    value.replace(phoneRegex, '($1) $2-$3')
  )
}

class FindASubscriber extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      value: ''
    }
  }

  render() {
    const { label, placeholder, feedback } = this.props
    const { value} = this.state
    return (
      <div className="find__a__subscriber">
        <FlexGrid>
          <FlexGrid.Col>
            <FlexGrid.Row>
              <Input
                feedback={feedback}
                label={label}
                type="text"
                pattern="[0-9]*"
                placeholder={placeholder}
                value={handleInput(value)}
                maxLength="10"
                onChange={
                 (event) => this.setState({value: event.target.value})
                }
              />
            </FlexGrid.Row>
          </FlexGrid.Col>
        </FlexGrid>
      </div>
    )
  }
}```
关注者
0
被浏览
99
1 个回答
  • 面试哥
    面试哥 2021-01-31
    为面试而生,有面试问题,就找面试哥。

    你可以normalizeinput像现在这样

    • 有关的value是最新的event.target.value
    • previousValue 是已经验证并设置为 state

    这种结构的结构可以防止无效字符更新输入,并将输入限制为10个数字。

    单击Run code snippet下面的按钮以获取工作示例。


    const normalizeInput = (value, previousValue) => {
      // return nothing if no value
      if (!value) return value;
    
      // only allows 0-9 inputs
      const currentValue = value.replace(/[^\d]/g, '');
      const cvLength = currentValue.length;
    
      if (!previousValue || value.length > previousValue.length) {
    
        // returns: "x", "xx", "xxx"
        if (cvLength < 4) return currentValue;
    
        // returns: "(xxx)", "(xxx) x", "(xxx) xx", "(xxx) xxx",
        if (cvLength < 7) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`;
    
        // returns: "(xxx) xxx-", (xxx) xxx-x", "(xxx) xxx-xx", "(xxx) xxx-xxx", "(xxx) xxx-xxxx"
        return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3, 6)}-${currentValue.slice(6, 10)}`; 
      }
    };
    
    
    
    const normalizeInput = (value, previousValue) => {
    
      if (!value) return value;
    
      const currentValue = value.replace(/[^\d]/g, '');
    
      const cvLength = currentValue.length;
    
    
    
      if (!previousValue || value.length > previousValue.length) {
    
        if (cvLength < 4) return currentValue;
    
        if (cvLength < 7) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`;
    
        return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3, 6)}-${currentValue.slice(6, 10)}`;
    
      }
    
    };
    
    
    
    const validateInput = value => {
    
      let error = ""
    
    
    
      if (!value) error = "Required!"
    
      else if (value.length !== 14) error = "Invalid phone format. ex: (555) 555-5555";
    
    
    
      return error;
    
    };
    
    
    
    class Form extends React.Component {
    
      constructor() {
    
        super();
    
    
    
        this.state = { phone: "", error: "" };
    
        this.handleChange = this.handleChange.bind(this);
    
        this.handleSubmit = this.handleSubmit.bind(this);
    
        this.handleReset = this.handleReset.bind(this);
    
      }
    
    
    
      handleChange({ target: { value } }) {
    
        this.setState(prevState=> ({ phone: normalizeInput(value, prevState.phone) }));
    
      };
    
    
    
      handleSubmit(e) {
    
        e.preventDefault();
    
        const error = validateInput(this.state.phone);
    
    
    
        this.setState({ error }, () => {
    
           if(!error) {
    
             setTimeout(() => {
    
               alert(JSON.stringify(this.state, null, 4));
    
             }, 300)
    
           }
    
        });
    
      }
    
    
    
      handleReset() {
    
         this.setState({ phone: "", error: "" });
    
      };
    
    
    
      render() {
    
        return(
    
          <form className="form" onSubmit={this.handleSubmit}>
    
            <div className="input-container">
    
              <p className="label">Phone:</p>
    
              <input
    
                className="input"
    
                type="text"
    
                name="phone"
    
                placeholder="(xxx) xxx-xxxx"
    
                value={this.state.phone}
    
                onChange={this.handleChange}
    
              />
    
              {this.state.error && <p className="error">{this.state.error}</p>}
    
            </div>
    
            <div className="btn-container">
    
              <button
    
                 className="btn danger"
    
                 type="button"
    
                 onClick={this.handleReset}
    
               >
    
                Reset
    
              </button>
    
              <button className="btn primary" type="submit">Submit</button>
    
            </div>
    
          </form>
    
        );
    
      }
    
    }
    
    
    
    ReactDOM.render(
    
      <Form />,
    
      document.getElementById('root')
    
    );
    
    
    html {
    
      font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
    
      font-size: 16px;
    
      font-weight: 400;
    
      line-height: 1.5;
    
      -webkit-text-size-adjust: 100%;
    
      background: #fff;
    
      color: #666;
    
    }
    
    
    
    .btn {
    
      color: #fff;
    
      border: 1px solid transparent;
    
      margin: 0 10px;
    
      cursor: pointer;
    
      text-align: center;
    
      box-sizing: border-box;
    
      padding: 0 30px;
    
      vertical-align: middle;
    
      font-size: .875rem;
    
      line-height: 38px;
    
      text-align: center;
    
      text-decoration: none;
    
      text-transform: uppercase;
    
      transition: .1s ease-in-out;
    
      transition-property: color,background-color,border-color;
    
    }
    
    
    
    .btn:focus {
    
      outline: 0;
    
    }
    
    
    
    .btn-container {
    
      text-align: center;
    
      margin-top: 10px;
    
    }
    
    
    
    .form {
    
      width: 550px;
    
      margin: 0 auto;
    
    }
    
    
    
    .danger {
    
      background-color: #f0506e;
    
      color: #fff;
    
      border: 1px solid transparent;
    
    }
    
    
    
    .danger:hover {
    
      background-color: #ee395b;
    
      color: #fff;
    
    }
    
    
    
    .error {
    
      margin: 0;
    
      margin-top: -20px;
    
      padding-left: 26%;
    
      color: red;
    
      text-align: left;
    
    }
    
    
    
    .input {
    
      display: inline-block;
    
      height: 40px;
    
      font-size: 16px;
    
      width: 70%;
    
      padding: 0 10px;
    
      background: #fff;
    
      color: #666;
    
      border: 1px solid #e5e5e5;
    
      transition: .2s ease-in-out;
    
      transition-property: color,background-color,border;
    
     }
    
    
    
    .input-container {
    
      width: 100%;
    
      height: 60px;
    
      margin-bottom: 20px;
    
      display: inline-block;
    
    }
    
    
    
    .label {
    
      width: 25%;
    
      padding-top: 8px;
    
      display: inline-block;
    
      text-align: center;
    
      text-transform: uppercase;
    
      font-weight: bold;
    
      height: 34px;
    
      border-top-left-radius: 4px;
    
      border-bottom-left-radius: 4px;
    
      background: rgb(238, 238, 238);
    
    }
    
    
    
    .primary {
    
      background-color: #1e87f0;
    
    }
    
    
    
    .primary:hover {
    
      background-color: #0f7ae5;
    
      color: #fff;
    
    }
    
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    
    
    
    
    <div id='root'>
    
    </div>
    

    或者…有3个单独的输入,完成后将它们合并。

    const validateInput = value => {
    
      let error = ""
    
    
    
      if (!value) error = "Required!"
    
      else if (value.length !== 14) error = "Invalid phone format. ex: (555) 555-5555";
    
    
    
      return error;
    
    };
    
    
    
    const initialState = {
    
     areaCode: "",
    
     prefix: "",
    
     suffix: "",
    
     error: ""
    
    };
    
    
    
    class Form extends React.Component {
    
      constructor() {
    
        super();
    
    
    
        this.state = initialState;
    
        this.handleChange = this.handleChange.bind(this);
    
        this.handleSubmit = this.handleSubmit.bind(this);
    
        this.handleReset = this.handleReset.bind(this);
    
        this.setInputRef = this.setInputRef.bind(this);
    
      }
    
    
    
      handleChange({ target: { name, value } }) {
    
        let valueChanged = false;
    
        this.setState(prevState => {
    
          const nextValue = value.replace(/[^\d]/g, '');
    
          const changedValue = prevState[name];
    
          if (changedValue.length !== nextValue.length) valueChanged = true;
    
    
    
          return { [name]: nextValue }
    
        }, () => {
    
          if(valueChanged) this.handleFocus(name)
    
        });
    
      };
    
    
    
      setInputRef(name, element) {
    
       this[name] = element;
    
      }
    
    
    
      handleFocus(name){
    
        const { areaCode, prefix, suffix } = this.state;
    
        const areaCodeFilled = areaCode.length === 3;
    
        const prefixFilled = prefix.length === 3;
    
    
    
        if(areaCodeFilled && name === "areaCode") {
    
          this.prefix.focus();
    
          this.prefix.selectionEnd = 0;
    
        } else if(prefixFilled && name === "prefix") {
    
          this.suffix.focus();
    
          this.suffix.selectionEnd = 0;
    
        }
    
      }
    
    
    
      handleSubmit(e) {
    
        e.preventDefault();
    
        const { areaCode, prefix, suffix } = this.state;
    
        const phoneNumber = `(${areaCode}) ${prefix}-${suffix}`
    
        const error = validateInput(phoneNumber);
    
    
    
        this.setState({ error }, () => {
    
           if(!error) {
    
             setTimeout(() => {
    
               alert(phoneNumber);
    
             }, 300)
    
           }
    
        });
    
      }
    
    
    
      handleReset() {
    
         this.setState(initialState);
    
      };
    
    
    
      render() {
    
        return(
    
          <form className="form" onSubmit={this.handleSubmit}>
    
            <div className="input-container">
    
              <div className="label">
    
                Phone:
    
              </div>
    
              <div className="parenthesis" style={{ marginLeft: 10, marginRight: 2}}>&#40;</div>
    
              <input
    
                className="input area-code"
    
                type="text"
    
                name="areaCode"
    
                placeholder="xxx"
    
                value={this.state.areaCode}
    
                onChange={this.handleChange}
    
                maxLength="3"
    
              />
    
               <div className="parenthesis" style={{ marginRight: 2}}>&#41;</div>
    
              <input
    
                ref={node => this.setInputRef("prefix", node)}
    
                className="input prefix"
    
                type="text"
    
                name="prefix"
    
                placeholder="xxx"
    
                value={this.state.prefix}
    
                onChange={this.handleChange}
    
                maxLength="3"
    
              />
    
              <div className="dash">-</div>
    
              <input
    
                ref={node => this.setInputRef("suffix", node)}
    
                className="input suffix"
    
                type="text"
    
                name="suffix"
    
                placeholder="xxxx"
    
                value={this.state.suffix}
    
                onChange={this.handleChange}
    
                maxLength="4"
    
              />
    
            </div>
    
             <p className="error">{this.state.error}</p>
    
            <div className="btn-container">
    
              <button
    
                 className="btn danger"
    
                 type="button"
    
                 onClick={this.handleReset}
    
               >
    
                Reset
    
              </button>
    
              <button className="btn primary" type="submit">Submit</button>
    
            </div>
    
          </form>
    
        );
    
      }
    
    }
    
    
    
    ReactDOM.render(
    
      <Form />,
    
      document.getElementById('root')
    
    );
    
    
    html {
    
      font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
    
      font-size: 16px;
    
      font-weight: 400;
    
      line-height: 1.5;
    
      -webkit-text-size-adjust: 100%;
    
      background: #fff;
    
      color: #666;
    
    }
    
    
    
    .btn {
    
      color: #fff;
    
      border: 1px solid transparent;
    
      margin: 0 10px;
    
      cursor: pointer;
    
      text-align: center;
    
      box-sizing: border-box;
    
      padding: 0 30px;
    
      vertical-align: middle;
    
      font-size: .875rem;
    
      line-height: 38px;
    
      text-align: center;
    
      text-decoration: none;
    
      text-transform: uppercase;
    
      transition: .1s ease-in-out;
    
      transition-property: color,background-color,border-color;
    
    }
    
    
    
    .btn:focus {
    
      outline: 0;
    
    }
    
    
    
    .btn-container {
    
      text-align: center;
    
      margin-top: 10px;
    
    }
    
    
    
    .form {
    
      width: 550px;
    
      margin: 0 auto;
    
    }
    
    
    
    .danger {
    
      background-color: #f0506e;
    
      color: #fff;
    
      border: 1px solid transparent;
    
    }
    
    
    
    .danger:hover {
    
      background-color: #ee395b;
    
      color: #fff;
    
    }
    
    
    
    .error {
    
      margin: 0;
    
      height: 24px;
    
      margin-top: -20px;
    
      padding-left: 26%;
    
      color: red;
    
      text-align: right;
    
    }
    
    
    
    .input {
    
      display: flex;
    
      height: 40px;
    
      font-size: 16px;
    
      width: 33%;
    
      padding: 0 3px;
    
      background: #fff;
    
      color: #666;
    
      outline: none;
    
      border: 0;
    
    }
    
    
    
    .area-code,.prefix {
    
     width: 27px;
    
    }
    
    
    
    .suffix {
    
     width: 38px;
    
    }
    
    
    
    .dash,.parenthesis {
    
     display: flex;
    
    }
    
    
    
    .input-container {
    
      width: 100%;
    
      margin-bottom: 20px;
    
      display: flex;
    
      flex-direction: row;
    
      align-items: center;
    
      border-top-left-radius: 4px;
    
      border-bottom-left-radius: 4px;
    
    
    
        border: 1px solid #e5e5e5;
    
      transition: .2s ease-in-out;
    
      transition-property: color,background-color,borde
    
    }
    
    
    
    .label {
    
      height: 100%;
    
      background: rgb(238, 238, 238);
    
      width: 25%;
    
      padding-top: 8px;
    
      display: flex;
    
      text-transform: uppercase;
    
      justify-content: space-around;
    
      font-weight: bold;
    
      height: 34px;
    
    }
    
    
    
    .primary {
    
      background-color: #1e87f0;
    
    }
    
    
    
    .primary:hover {
    
      background-color: #0f7ae5;
    
      color: #fff;
    
    }
    
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    
    
    
    
    <div id='root'>
    
    </div>
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看