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

inb24sb2  于 2023-02-21  发布在  Java
关注(0)|答案(6)|浏览(128)

我需要将一个10位字符串格式化为以下格式:'(123)456- 7890'。但是,我需要在用户键入时发生这种情况。因此,如果用户仅输入了3个数字,则输入应显示:“(123)”。如果他们输入了5位数字,则输入应显示:(一二三)四十五
用我目前的代码,格式化只发生在输入第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>
    )
  }
}```
r7knjye2

r7knjye21#

你可以像这样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)}`; 
  }
};

x一个一个一个一个x一个一个二个一个x一个一个三个一个
或者...有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>
798qvoo8

798qvoo82#

关键在于格式。任何打印字符的键
应该会导致输入字段的重写。
这样,无论用户做什么,他都只能看到有效的格式化字段。
正则表达式是简单的^\D*(\d{0,3})\D*(\d{0,3})\D*(\d{0,4})

function getFormattedPhoneNum( input ) {
  let output = "(";
  input.replace( /^\D*(\d{0,3})\D*(\d{0,3})\D*(\d{0,4})/, function( match, g1, g2, g3 )
      {
        if ( g1.length ) {
          output += g1;
          if ( g1.length == 3 ) {
              output += ")";
              if ( g2.length ) {
                  output += " " + g2; 
                  if ( g2.length == 3 ) {
                      output += " - ";
                      if ( g3.length ) {
                          output += g3;
                      }
                  }
              }
           }
        }
      }       
    );        
  return output;
 }       

console.log( getFormattedPhoneNum("") );
console.log( getFormattedPhoneNum("2") );
console.log( getFormattedPhoneNum("asdf20as3d") );
console.log( getFormattedPhoneNum("203") );
console.log( getFormattedPhoneNum("203-44") );
console.log( getFormattedPhoneNum("444sg52asdf22fd44gs") );
console.log( getFormattedPhoneNum("444sg526sdf22fd44gs") );
console.log( getFormattedPhoneNum("444sg526sdf2244gs") );
console.log( getFormattedPhoneNum(" ra098 848 73653k-atui ") );

你甚至可以更好的显示下划线
应该是在任何给定的时间。
喜欢
(___) ___ - ____
(20_) ___ - ____
(123) 456 - ____
等等......(如果你想要这个,让我知道)

cs7cruho

cs7cruho3#

当前代码的正则表达式仅在输入10位数字(3、3、4)时匹配。您可以更新正则表达式以接受一定范围的数字,例如:

^\(?([0-9]{0,3})\)?[-. ]?([0-9]{0,3})[-. ]?([0-9]{0,4})$

或者,您可以让正则表达式确保输入了0-10个数字([0-9]{0,10}),然后自己将字符串拆分为长度为3、3和4的子字符串。后一种方法似乎更好,因为您只想根据用户输入的数字显示某些字符:
1 -〉(1
123 -〉(123)
1234567 -〉(123)456-7
电话:1234567890 -〉(123)456-7890
您必须处理这些情况中的每一种,而简单的替换无法做到这一点。

xxhby3vn

xxhby3vn4#

我使用过这个库:https://www.npmjs.com/package/libphonenumber-js它有一个AsYouType函数,您可以在输入中使用它

au9on6nz

au9on6nz5#

也许,下面的一些东西会对某人起作用:

onChange={(e) => {
                if (e.target.value.length < 13) {
                  var cleaned = ("" + e.target.value).replace(/\D/g, "");

                  let normValue = `${cleaned.substring(0, 3)}${
                    cleaned.length > 3 ? "-" : ""
                  }${cleaned.substring(3, 6)}${
                    cleaned.length > 6 ? "-" : ""
                  }${cleaned.substring(6, 11)}`;

                  handleChange(normValue);
                }
              }}
xoshrz7s

xoshrz7s6#

使用这个包https://www.npmjs.com/package/react-number-formatter,这个输入组件格式化数字并只返回数字。

相关问题