你们在作移动端开发的时候,想必必定会遇到拉起系统自带的键盘吧。最近接到需求, 想要拉起数字的键盘,只容许用户输入数字和小数点,并且在用户失去焦点的同时,将输入框的内容进行千分位,聚焦的时候还能够删除。 看似几个需求,但还真很差整。针对此需求,笔者考虑了三种方案,建议选择第二种(简单粗暴),由于第一种真的是在浪费生命,它会给你无尽的深渊~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值写死就好。咱们目前采用的方案就是这种。
以上呢,是在写这个东西踩的坑,阅读的童靴若有用,请点个小赞再走呗。若有错误,欢迎指正。