概述
目标 做一个金额输入框 要求 只需输入 数字 或者 小数点 不准输入非法数字 如 1.1. 或者 1..2 数字最大输入到两位小数 如 1.22, 不可输入 1.222 此时我们只讨论系统键盘。 自定义键盘不可取因为输入框不能获取焦点, 自定义键盘需要搭配特定的输入框也就是没有光标的那种才合适 解决方案的常规手段无外乎一下三种 监听 keyup/keydown/keypress目标
做一个金额输入框
要求
只需输入 数字 或者 小数点 不准输入非法数字 如 1.1. 或者 1..2 数字最大输入到两位小数 如 1.22, 不可输入 1.222 此时我们只讨论系统键盘。 自定义键盘不可取因为输入框不能获取焦点, 自定义键盘需要搭配特定的输入框也就是没有光标的那种才合适
解决方案的常规手段无外乎一下三种
- 监听 keyup/keydown/keypress 事件 通过 event.keycode 判断keycode的值来 return false还是true 此种体验最优,页面没有闪动 ( 存在部分兼容性)
- 监听 keyup/keydown/keypress 事件 通过 event.target.value 得到当前输入的值 通过 正则匹配来过滤是否替换为空 ( 存在部分兼容性)
-
监听 input 事件 通过 event.target.value 得到当前全部的输入值,但是当用户移动光标后在输入无法得知当前输入的是什么值, ( 完全兼容,但是没有什么乱用)
所以解决方案只有通过第一条或者第二条
在分析一下 input type 的取值
- type =text 弹出的非数字键盘 体验最差 有限排除
- type = number 弹出数字键盘,缺点 event.target.value 只能取到被过滤后的数字
- type= tel 弹出数字键盘 event.target.value 可以取到正确值, 但是在ios下弹出的软键盘 没有‘.‘
先来一段小前提,一下为亲测
在中文状态下在keycode 都是229
- AndroID手机 弹出的软键盘默认为中文状态 所以code码 都是229
- ios手机 弹出的软键盘默认为英文文状态 所以code码可以用
- ios手机在
<input type=tel>
弹出的软键盘 只有1-9 没有 ‘.’ <input type="number">
这种形式 event.target.value 得到的值只有纯数字,也就是输入12.... 的时候 event.target.value =12
所以解决方案呼之欲出
- 在androID 下
input type=tel
监听 keyup事件, event.target.value 通过正则过滤输入 - 在ios下
input type=number
通过 keypress 事件 event.keycode 过滤输入,
部分参考 https://cloud.tencent.com/developer/article/1098877
一下是我对以上的一个简单实现
<template> <x-cell :Title="label" :isBordorBootom = 'isBordorBootom' v-clickoutsIDe="doCloseActive" :class="[{ 'is-textarea': type === 'textarea','is-nolabel': !label }]"> <div class="mint-fIEld"> <textarea @change="$emit('change',currentValue)" ref="textarea" class="mint-fIEld-core" :placeholder="placeholder" v-if="type === 'textarea'" :rows="rows" :Disabled="Disabled" :Readonly="Readonly" v-model="currentValue"> </textarea> <div class="input-waper" v-else > <div class="prefix"> <slot name="prefix"></slot> </div> <input @change="$emit('change',currentValue)" ref="input" class="mint-fIEld-core" :placeholder="placeholder" :maxlength="maxlength" :number="type === 'number'" :type="type" :style="`Font-size:${FontSize}; paddingleft:${paddingleft}`" @focus="focus" @blur="$emit('blur')" :Disabled="Disabled" :Readonly="Readonly" :value="currentValue" @keyup="handleKeyup" @keypress="handleKeypress" @input="handleinput"> <div @click="handleClear" class="mint-fIEld-clear" v-if="!disableClear" v-show="(currentValue !== '') && type !== 'textarea' && active"> <!-- <i class="mintui mintui-fIEld-error"></i> --> <img src="./[email protected]" class="mint-fIEld-clear-img"> </div> <div class="afterfix"> <slot name="afterfix"></slot> </div> </div> </div> </x-cell> </template> <script> import XCell from '../../cell/src/cell'; import ClickoutsIDe from '../../../src/utils/clickoutsIDe'; import icon from '../../icon/src/icon' /** * mt-fIEld * @desc 编辑器,依赖 cell * @module components/fIEld * * @param {string} [type=text] - fIEld 类型,接受 text,textarea 等 * @param {string} [label] - 标签 * @param {string} [rows] - textarea 的 rows * @param {string} [placeholder] - placeholder * @param {string} [Disabled] - Disabled * @param {string} [Readonly] - Readonly * @param {string} [state] - 表单校验状态样式,接受 error,warning,success * * @example * <mt-fIEld v-model="value" label="用户名"></mt-fIEld> * <mt-fIEld v-model="value" label="密码" placeholder="请输入密码"></mt-fIEld> * <mt-fIEld v-model="value" label="自我介绍" placeholder="自我介绍" type="textarea" rows="4"></mt-fIEld> * <mt-fIEld v-model="value" label="邮箱" placeholder="成功状态" state="success"></mt-fIEld> */ export default { name: 'CommonFIEld',data() { return { active: false,currentValue: this.value }; },directives: { ClickoutsIDe },props: { type: { type: String,default: 'text' },rows: String,label: String,placeholder: String,Readonly: Boolean,Disabled: Boolean,disableClear: Boolean,state: { type: String,default: 'default' },value: {},attr: Object,isBordorBootom: { type: Boolean,default: false },FontSize: String,paddingleft: String,maxlength: Number },components: { XCell,icon },methods: { doCloseActive() { this.active = false; },handleinput(evt) { this.currentValue = evt.target.value console.log('handleinput:',evt) },handleKeydown(evt) { console.log('handleKeydown:',evt) if (this.type === 'number') { const keyCode = evt.keyCode; const inputVal = this.$refs.input.value if (this.isNotNumberKeycode(keyCode) || this.isDotStart(keyCode,inputVal)) { console.log('组织') evt.preventDefault(); evt.stopPropagation(); return false; } } },handleKeypress(evt) { console.log('handleKeypress:',inputVal)) { evt.preventDefault(); evt.stopPropagation(); return false; } } },isBackspace(keyCode) { return keyCode === 8; },isDot(keyCode) { return keyCode === 46 || keyCode === 190; },isNumber(keyCode) { return (keyCode >= 48 && keyCode <= 57); },isDotStart(keyCode,inputVal) { return this.isDot(keyCode) && (!inputVal || inputVal === '' || /\./.test(inputVal)); },isNotNumberKeycode(keyCode) { return !this.isBackspace(keyCode) && !this.isDot(keyCode) && !this.isNumber(keyCode); },handleKeyup(evt) { console.log('handleKeyup:',evt) if (this.type === 'number' || this.type === 'tel') { let val = evt.target.value console.log('原来的val:',val) val = val.replace(/[^\d.]/g,'') //清除“数字”和“.”以外的字符 val = val.replace(/\.{2,}/g,'.') //只保留第一个. 清除多余的 连续两个 val = val.replace('.','$#$').replace(/\./g,'').replace('$#$','.') //只保留第一个. 清除多余的 非连续两个 val = val.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3') //只能输入两个小数 if(val.indexOf('.')< 0 && val != ''){ //以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额 val = parsefloat(val) } console.log(val) // this.currentValue = evt.target.value.replace(/[^\d]/g,''); this.currentValue = val } },handleClear() { if (this.Disabled || this.Readonly) return; this.currentValue = ''; this.$emit('handleClear') },focus() { this.active = true this.$emit('focus') } },computed: { iconState() { if (this.state === 'default') { return '' } else if (this.state === 'error') { return '' } else if (this.state === 'warning') { return '' } else if (this.state === 'success') { return '' } else { return '' } },showClear() { } },watch: { value(val) { this.currentValue = val; },currentValue(val) { this.$emit('input',val); },attr: { immediate: true,handler(attrs) { this.$nextTick(() => { const target = [this.$refs.input,this.$refs.textarea]; target.forEach(el => { if (!el || !attrs) return; Object.keys(attrs).map(name => el.setAttribute(name,attrs[name])); }); }); } } } }; </script> <style lang="sCSS" scoped> @import "../../../src/style/var.sCSS"; input { Font-family: The1Official_Bold ; } .mint-fIEld { wIDth: 100%; } .mint-fIEld.is-textarea { -webkit-Box-align: inherit; -ms-flex-align: inherit; align-items: inherit; } .input-waper { // border-bottom: 1px solID #EEEEEE; // padding: .3rem 0 .3rem 0; border-bottom: 1px solID #A1A5B9; padding-right: 5px; display: flex; // height: 1.1rem; // padding: .28rem 0rem .27rem 0rem; position: relative; Box-sizing: border-Box; .mint-fIEld-core { border: 0; padding: 0; display: block; wIDth: 100%; resize: none; Box-sizing: border-Box; Font-size: .46rem; outline:none; color: $color-red; padding-right: .5rem; } .prefix { display: flex; flex-direction: column; justify-content: center; } .afterfix { display: flex; flex-direction: column; justify-content: flex-end; padding-bottom: .4rem; } ::-webkit-input-placeholder { /* WebKit browsers */ color: $color-red; opacity: .5; } :-moz-placeholder { /* Mozilla firefox 4 to 18 */ color: $color-red; opacity: .5; } ::-moz-placeholder { /* Mozilla firefox 19+ */ color: $color-red; opacity: .5; } :-ms-input-placeholder { /* Internet Explorer 10+ */ color: $color-red; opacity: .5; } } // 去除number右侧箭头 input::-webkit-outer-spin-button,input::-webkit-inner-spin-button { -webkit-appearance: none !important; margin: 0; } .mint-fIEld-clear { display: flex; justify-content: center; align-items: flex-end; padding-bottom: .4rem; padding-right: .2rem; } .mint-fIEld-clear-img { wIDth: 14px; height: 14px; } .mint-fIEld-state { color: inherit; margin-left: 20px; } .mint-fIEld-state .mintui { Font-size: 20px; } .mint-fIEld-state.is-default { margin-left: 0; } .mint-fIEld-state.is-success { color: #4caf50; } .mint-fIEld-state.is-warning { color: #ffc107; } .mint-fIEld-state.is-error { color: #f44336; } .mint-fIEld-other { top: 0; right: 0; position: relative; } </style>
总结
以上是编程之家为你收集整理的金额输入框 在 hybrid 下 ios/android h5 处理情况全部内容,希望文章能够帮你解决金额输入框 在 hybrid 下 ios/android h5 处理情况所遇到的程序开发问题。
如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。