移动端h5实现假键盘,假输入框,假input框

为什么要做这个呢,微信端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  这是真的全套的,毕竟我没有去实现点击数字去移动光标,

这个会复杂很多,先暂且实现这样!!

猜你喜欢

转载自blog.csdn.net/shentibeitaokong/article/details/80834097