你們在作移動端開發的時候,想必必定會遇到拉起系統自帶的鍵盤吧。最近接到需求, 想要拉起數字的鍵盤,只容許用戶輸入數字和小數點,並且在用戶失去焦點的同時,將輸入框的內容進行千分位,聚焦的時候還能夠刪除。 看似幾個需求,但還真很差整。針對此需求,筆者考慮了三種方案,建議選擇第二種(簡單粗暴),由於第一種真的是在浪費生命,它會給你無盡的深淵~css
廢話很少說,先來分析一波。react
以上是實現這個的具體思路,接下來就迎接各大機型的兼容性問題吧,放心,會讓你開心到飛起。web
input.tsxbash
import React from 'react'
import {Images} from "config/index";
import './style.scss'
interface Props {
isFormat?: Boolean,
isShowAll?: Boolean,
val?: any,
handleFormat: Function,
handleChange?: Function,
handleDel?: Function,
handleAll?: Function,
placeholder?: any,
small?: any
isShowDelIcon?: Boolean,
disabled?: Boolean
}
export default class BcInputMoney extends React.Component<any, any>{
constructor(props) {
super(props)
this.state = {
inputType: 'number' // 初始是number類型
}
}
handleChange = (e) => {
let val = e.target.value
// 動態替換異樣字符
val = val.replace(/^\D*(\d*(?:\.\d{0,2})?).*$/g, '$1').replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
val = val.replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.').replace('.', '$#$').replace(/\./g, '').replace('$#$', '.').replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3').replace(/^\./g, '')
this.props.handleChange(e, val)
}
handleDel = () => {
const { isFormat } = this.props
if (isFormat) { // 表示須要格式化
this.setState({
inputType: 'number'
})
}
this.props.handleDel()
}
handleAll = () => {
this.props.handleAll()
}
handleBlur = () => {
const { isFormat, val } = this.props
if (isFormat && val) { // 表示須要格式化
if (val <= 999) {
// 由於 999.00 格式化的時候 和 不格式化的時候 值是一致的,因此動態改變成text的時候第一次拉不起鍵盤
this.setState({
inputType: 'number'
})
} else {
this.setState({
inputType: 'text'
})
}
this.props.handleFormat('blur')
}
}
handleFoucs = () => {
const { isFormat, val } = this.props
if (isFormat && val) { // 表示須要格式化
this.setState({
inputType: 'number'
})
this.props.handleFormat('focus')
}
}
render() {
const { isShowAll, val, placeholder, small, isShowDelIcon = true, disabled = false, type } = this.props
let { inputType } = this.state
return (
<div className="bc-money-input-box">
<span className="unit">¥</span>
<div className="inputs">
<input
pattern="[0-9]*"
className={"money-input " + (small ? small : '')}
disabled={disabled}
type={inputType}
value={ val == null ? '' : val }
placeholder={ placeholder ? placeholder : '請輸入金額'}
onBlur={this.handleBlur}
onFocus={this.handleFoucs}
onChange={this.handleChange}/>
</div>
<div className={`del-img ${isShowDelIcon ? '' : 'hidden'}`} onClick={ this.handleDel }>
<img src={Images.delIcon} alt="" width="16" height="17"/>
</div>
<div className={`all ${isShowAll ? '' : 'hidden'}`} onClick={ this.handleAll }>所有</div>
</div>
)
}
}
複製代碼
style.scssflex
.bc-money-input-box{
background: #FFFFFF;
min-height: px2rem(38);
display: flex;
align-items: center;
justify-content: space-between;
font-family:PingFangSC-Regular;
font-weight:400;
margin-left: px2rem(15);
.unit{
padding-right: px2rem(10);
font-size: px2rem(22);
color:rgba(51,51,51,1);
width: px2rem(12);
}
.inputs{
flex: 1;
.money-input{
height: px2rem(38);
width: 100%;
border: none;
outline: none;
box-sizing: border-box;
font-size: px2rem(24);
font-family:PingFangSC-Medium;
font-weight:500;
color:rgba(51,51,51,1) !important;
background: transparent;
}
}
.del-img{
width: px2rem(20);
height: px2rem(38);
margin-right: px2rem(10);
display: flex;
align-items: center;
}
.all{
width: px2rem(35);
margin-left: px2rem(-4);
padding-right: px2rem(15);
font-size: px2rem(16);
color:rgba(80,140,238,1);
line-height: px2rem(38);
}
.hidden{
display: none;
}
}
.money-input::-webkit-input-placeholder {
font-size: px2rem(24);
font-family:PingFangSC-Regular;
display: flex;
line-height:normal;
align-items: center;
color:rgba(153,153,153,1);
background: transparent;
transform: translate(0, 0);
-ms-transform:translate(0, 0); /* IE 9 */
-moz-transform:translate(0,0); /* Firefox */
-webkit-transform:translate(0, 0); /* Safari 和 Chrome */
-o-transform:translate(0, 0);
}
.s::-webkit-input-placeholder {
font-size: px2rem(16);
line-height: px2rem(38);
font-family:PingFangSC-Regular;
color:rgba(153,153,153,1);
background: transparent;
transform: translate(0, 0);
-ms-transform:translate(0, 0); /* IE 9 */
-moz-transform:translate(0,0); /* Firefox */
-webkit-transform:translate(0, 0); /* Safari 和 Chrome */
-o-transform:translate(0, 0);
}
複製代碼
頁面中使用該組件的方法ui
import React from 'react'
import {observer, inject} from 'mobx-react'
import { BcButton, BcInputMoney } from 'container/index'
import help from 'utils/Tool'
@inject('store')
@observer
export default class Demo extends React.Component<any, any> {
state = {
money: ''
}
changeMoney = (e, val) => { // 子組件調用的方法
this.setState({
money: val
})
}
FormatMoney = (type) => { // 格式話當前的內容
let { money } = this.state
if (money.indexOf('.') == money.length - 1) {
money = money.replace('.', '')
}
if (type == 'focus') {
this.setState({
money: help.clearComma(money)
})
}
if (type == 'blur') {
this.setState({
money: help.formatNum(money.toString())
})
}
}
delMoney = () => { // 清空當前值
if (this.state.money) {
this.setState({
money: ''
})
}
}
render () {
let { money } = this.state
return (
<div className="box">
<BcInputMoney
isFormat={true}
isShowDelIcon={money}
isShowAll={false}
val={money}
handleDel={this.delMoney}
handleChange={this.changeMoney}
handleFormat={this.FormatMoney}
placeholder={'請輸入充值金額'} />
<BcButton className="recharge">充值</BcButton>
</div>
)
}
}
複製代碼
以上呢就是組件之間的通訊,你們花下心思必懂,給你們說下如下代碼存在的問題。this
錘子spa
華爲code
小米、vivoorm
這只是針對幾個問題作出來的處理。再次細化安卓各類的機型,問題想必也不會少,因此別浪費生命啦~
咱們能夠轉換一種思路,第一種咱們一直在input上作事情,作完可能這個機型能夠,另外一個機型又是另外一種問題,因此咱們 可不能夠把側重點放在輸入完內容以後點擊的按鈕上,輸入完內容,用戶確定操做按鈕下一步操做,咱們在這裏攔截是否符合咱們的規範 ,不用考慮兼容問題,咱們開發也方便,更況且輸入錯誤的格式的用戶也應該很少。
上代碼(同上,就是添加下一步按鈕的事件,把input的change事件的替換正則的給幹掉)
let { money } = this.state
const regMoney = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/ // 金錢
const fixedTwo = /^\d*(\.?\d{0,2})/g // 輸入框對金額限制小數點後兩位
let val = help.clearComma(money)
if (regMoney.test(val) && fixedTwo.test(val)) {
console.log('舒適提示,您輸入的內容格式有誤')
} else {
console.log('輸入框的內容格式正確,下一步吧')
}
複製代碼
脫離了需求的軌跡,不在動態改變input的type值,上來就是text,這樣存在的問題少,可是就是拉起鍵盤的是英文鍵盤。代碼同上,把input的type值寫死就好。咱們目前採用的方案就是這種。
以上呢,是在寫這個東西踩的坑,閱讀的童靴若有用,請點個小贊再走唄。若有錯誤,歡迎指正。