为什么要做这个呢,微信端ios选择type=tel 没有小数点,选择type=number有一大堆的非数字字符,当然你可以用keycode来判断去禁用非数字的点击,何况,这种类型的input框 会将
只要输入框内的字符串不能转换成浮点数,它的值就变为空了
so当然就不考虑了,那网上搜了一下,发现还可以啊,简单写一个, 实现功能:
- 键盘带有小数点,并可以自动弹出
- 限制整数与小数的位数,超过就不能输入
- 无法连续输入不正常的数字
- 如果第一次输入'.' ,自动变为 '0.'
- 输入例如 100 或者 100. 或者 100.0 自动 变为 100.00
因为项目上用的是vux,so将别人的源代码改了一改来适应自己的项目,效果:
代码分为 keyboard.vue 键盘
<style scoped lang="less">
.keyboard {
height: 200px;
width: 100%;
background: white;
z-index: 999;
.list {
height: 200px;
.key:active {
background: #e2e2e2;
}
.key {
width: 100%;
box-sizing: border-box;
border-right: .5px solid #d6d6d6;
border-top: .5px solid #d6d6d6;
display: flex;
align-items: center;
justify-content: center;
font-size: 30px;
}
.key:nth-child(3n) {
border-right: none;
}
}
.key {
line-height: 49px!important;
}
}
.del {
font-size: 28px;
}
.animated {
animation-duration: .2s;
animation-fill-mode: both;
}
@keyframes slideInDown {
from {
transform: translate3d(0, 0, 0);
visibility: visible;
}
to {
transform: translate3d(0, 100%, 0);
display: none;
}
}
@keyframes slideInUp {
from {
transform: translate3d(0, 100%, 0);
visibility: visible;
}
to {
transform: translate3d(0, 0, 0);
}
}
.slide-enter-active {
animation-name: slideInUp;
}
.slide-leave-active {
animation-name: slideInDown;
}
</style>
<template>
<transition name="slide">
<div class="keyboard animated" v-show="show" @touchstart.stop.prevent="fn">
<!-- 键盘区域 -->
<div class="list">
<flexbox orient="vertical" :gutter="0">
<flexbox-item>
<flexbox :gutter="0">
<flexbox-item>
<div class="key" @touchstart="typing('1')">1</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('2')">2</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('3')">3</div>
</flexbox-item>
</flexbox>
</flexbox-item>
<flexbox-item>
<flexbox :gutter="0">
<flexbox-item>
<div class="key" @touchstart="typing('4')">4</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('5')">5</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('6')">6</div>
</flexbox-item>
</flexbox>
</flexbox-item>
<flexbox-item>
<flexbox :gutter="0">
<flexbox-item>
<div class="key" @touchstart="typing('7')">7</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('8')">8</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('9')">9</div>
</flexbox-item>
</flexbox>
</flexbox-item>
<flexbox-item>
<flexbox :gutter="0">
<flexbox-item>
<div class="key" @touchstart="typing('.')">
<wx-dl-icon type="dian" size=".5rem"></wx-dl-icon>
</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('0')">0</div>
</flexbox-item>
<flexbox-item>
<div class="key" @touchstart="typing('')">
<wx-dl-icon type="jianpanshanchu" size=".5rem"></wx-dl-icon>
</div>
</flexbox-item>
</flexbox>
</flexbox-item>
</flexbox>
</div>
</div>
</transition>
</template>
<script>
import {Group, Flexbox, FlexboxItem} from 'vux'
import WxDlIcon from '../wx-dl-icon'
export default {
components: {WxDlIcon, Group, Flexbox, FlexboxItem},
props: ['show'],
data () {
return {
}
},
methods: {
/* 防止点击完成按钮左边的空白区域收起键盘 */
fn () {},
/* 输入 */
typing (val) {
this.$emit('typing', val)
},
/* 点击完成 */
complete () {
this.$emit('complete')
}
}
}
</script>
2 input.vue 输入框
<style scoped lang="less">
.wx-keyboard {
.keyInput {
.title {
color: #bbb;
font-size: .6rem;
text-align: center;
margin-top: 0.5rem;
}
.box {
border: 1px solid #ccc;
height: 24px;
padding: 5px;
margin: 10px;
}
.input-box {
display: flex;
align-items: center;
justify-content: flex-end;
line-height: 22px;
.content {
display: flex;
.input {
font-size: 20px;
color: #313131;
}
.cursor {
background-color: #4788c5;
width: 2px;
margin-left: 2px;
}
.placeholder {
color: #ccc;
}
}
}
}
}
</style>
<template>
<div class="wx-keyboard">
<div>
<flexbox class="keyInput">
<flexbox-item style="padding-top: 33px" :span="2/15" align="right">¥</flexbox-item>
<flexbox-item class="request-amount__input" :span="10/15">
<group>
<div class="title">
请填写还款金额
</div>
<div class="box">
<div class="input-box" @touchstart.stop="focus">
<div class="content">
<p class="input">
{{val}}
</p>
<p class="placeholder" v-show="val.length === 0 && showPlaceholder">
{{placeholder}}
</p>
<!-- 光标 -->
<p class="cursor" :style="{visibility: cursor ? 'visible' : 'hidden'}"></p>
</div>
</div>
</div>
</group>
</flexbox-item>
<flexbox-item style="padding-top: .45rem" :span="2/15" align="center" @click.native="receiptAmountClose">
完成
</flexbox-item>
</flexbox>
</div>
<!--自定义键盘-->
<keyboard
:show="keyboard"
@typing="typing"/>
</div>
</template>
<script>
import keyboard from './keyboard'
import {Group, Flexbox, FlexboxItem} from 'vux'
export default {
name: 'KeyboardInput',
components: {
keyboard,
Group,
Flexbox,
FlexboxItem
},
created () {
document.addEventListener('touchstart', () => {
this.focus()
})
},
props: {
value: '',
inter: {
default: 10
},
decimal: {
default: 2
},
showPlaceholder: {
type: Boolean,
default: true
},
label: {
default: '消费金额'
},
placeholder: {
default: '请填写金额'
}
},
data () {
return {
cursor: false,
keyboard: true,
/* value 在组件中的值 */
val: '',
aIllegal: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0..', '..'],
cursorDuration: 600,
bodyHeight: '',
bodyOverflow: ''
}
},
methods: {
/* focus */
focus () {
/* 显示键盘 */
this.showKeyboard()
/* 显示光标 */
this.showCursor()
/* 闪烁光标 */
this.blinkCursor()
},
blinkCursor () {
clearInterval(this.intervalID)
this.intervalID = setInterval(() => {
this.cursor = !this.cursor
}, this.cursorDuration)
},
unblinkCursor () {
clearInterval(this.intervalID)
},
/* blur */
blur () {
/* 隐藏光标 */
this.hideCursor()
/* 停止光标闪烁 */
this.unblinkCursor()
/* 隐藏键盘 */
// this.hideKeyboard()
/*
附加 00, 如果用户输入了一个以 . 结尾的值就点完成了,
那么这个时候就在后面加上00
*/
this.toCompletion()
/* 通知父组件, 老子值出来了 */
this.notify()
},
showKeyboard () {
this.keyboard = true
},
hideKeyboard () {
this.keyboard = false
},
showCursor () {
this.cursor = true
},
hideCursor () {
this.cursor = false
},
checkValue () {
if (parseFloat(this.val) === 0) {
this.val = ''
}
},
/* 判读是否需要加0 */
toCompletion () {
let list = this.value.split('.')
if (typeof list[1] === 'undefined') {
if (this.val !== '') {
this.val = this.val + '.'
this.completion(this.decimal)
}
} else {
if (list[1].length < this.decimal) {
this.completion(this.decimal - list[1].length)
}
}
},
completion (len) {
let v = ''
for (let i = 0; i < len; i++) {
v = v + '0'
}
this.val = this.val + v
},
notify () {
this.$emit('input', this.val)
},
del () {
/* 删除值并不会触发值的校验, 所以需要手动再触发一次 */
this.val = this.val.slice(0, -1)
this.notify()
},
/* 输入 */
typing (value) {
/* 如果是点击删除 */
if (value === '') {
this.del()
}
/* 保存旧的值 */
let oldValue = this.val
/* 获取新的值 */
this.val = this.val + value
/* 检验新值, 如果没有通过检测, 恢复值 */
if (!this.passCheck(this.val)) {
this.val = oldValue
return
}
if (this.val === '.') {
this.val = '0.'
}
/* 为了让外界同步输入, 需要发送事件 */
this.notify()
},
passCheck (val) {
/* 验证规则 */
let aRules = [
this.illegalInput,
this.illegalValue,
this.accuracy
]
return aRules.every((item) => {
return item(val)
})
},
illegalInput (val) {
if (this.aIllegal.indexOf(val) > -1) {
return false
}
return true
},
/* 非法值 */
illegalValue (val) {
if (val === '.') {
return true
} else {
if (parseFloat(val) !== Number(val)) {
return false
}
return true
}
},
/* 验证精度 */
accuracy (val) {
let v = val.split('.')
if (v[0].length > this.inter) {
return false
}
if (v[1] && (v[1].length) > this.decimal) {
return false
}
return true
},
receiptAmountClose () {
this.blur()
this.$emit('complete', this.val)
}
}
}
</script>
引用
<wx-keyboard
inter="10"
decimal="2"
@complete="receiptAmountClose"
v-model="receiptAmount">
</wx-keyboard>
这里需要感谢 ,基本上参考这个的 https://github.com/helicopters/wc-keyboard,这个是通用的,可以根据自己的项目要求去改变
推荐 https://zhuanlan.zhihu.com/p/30360629 这是真的全套的,毕竟我没有去实现点击数字去移动光标,
这个会复杂很多,先暂且实现这样!!