使用vue实现模拟键盘(字母,数字),支持移动端和pc端(2)


Keyboard.vue

<template>
  <div class="keyboard" v-show="showKeyboard" v-clickoutside="closeModal">
    <p v-for="keys in keyList">
      <template v-for="key in keys">
        <i v-if="key === 'top'" @click.stop="clickKey" @touchend.stop="clickKey" class="iconfont icon-zhiding tab-top"></i>
        <i v-else-if="key === '123'" @click.stop="clickKey" @touchend.stop="clickKey" class="tab-num">123</i>
        <i v-else-if="key === 'del'" @click.stop="clickKey" @touchend.stop="clickKey" class="iconfont icon-delete key-delete"></i>
        <i v-else-if="key === 'blank'" @click.stop="clickKey" @touchend.stop="clickKey" class="iconfont icon-konggejian-jianpanyong tab-blank"></i>
        <i v-else-if="key === 'symbol'" @click.stop="clickKey" @touchend.stop="clickKey" class="tab-symbol">符</i>
        <i v-else-if="key === 'point'" @click.stop="clickKey" @touchend.stop="clickKey" class="tab-point">·</i>
        <i v-else-if="key === 'enter'" @click.stop="clickKey" @touchend.stop="clickKey" class="iconfont icon-huiche tab-enter"></i>
        <i v-else @click.stop="clickKey" @touchend.stop="clickKey">{{key}}</i>
      </template>
    </p>
  </div>
</template>

<script>
import clickoutside from '../directives/clickoutside'

export default {
  directives: { clickoutside },
  data() {
    return {
      keyList: [],
      status: 0,//0 小写 1 大写 2 数字 3 符号
      lowercase: [
        ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
        ['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
        ['top', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'del'],
        ['123', 'point', 'blank', 'symbol', 'enter']
      ],
      uppercase: [
        ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
        ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
        ['top', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', 'del'],
        ['123', 'point', 'blank', 'symbol', 'enter']
      ],
      equip:!!navigator.userAgent.toLocaleLowerCase().match(/ipad|mobile/i)//是否是移动设备
    }
  },
  props: {
    option: {
      type: Object
    }
  },
  computed: {
    showKeyboard(){
      return this.option.show
    }
  },

  mounted() {
    this.keyList = this.lowercase
  },

  methods: {
    tabHandle({ value = '' }) {
      if(value.indexOf('tab-num') > -1){
         this.status = 2
         //数字键盘数据
      }else if(value.indexOf('key-delete') > -1){
        this.emitValue('delete')
      }else if(value.indexOf('tab-blank') > -1){
        this.emitValue(' ')
      }else if(value.indexOf('tab-enter') > -1){
        this.emitValue('\n')
      }else if(value.indexOf('tab-point') > -1){
        this.emitValue('.')
      }else if(value.indexOf('tab-symbol') > -1){
        this.status = 3
      }else if(value.indexOf('tab-top') > -1){
        if(this.status === 0){
          this.status = 1
          this.keyList = this.uppercase
        }else{
          this.status = 0
          this.keyList = this.lowercase
        }
      }else{

      }
    },

    clickKey(event) {
      if(event.type === 'click' && this.equip) return
      let value = event.srcElement.innerText
      value && value !== '符' && value !== '·' && value !== '123'? this.emitValue(value) : this.tabHandle(event.srcElement.classList)
    },

    emitValue(key) {
      this.$emit('keyVal', key)
    },

    closeModal(e) {
      if (e.target !== this.option.sourceDom) {
        // this.showKeyboard = false
        this.$emit('close', false)
      }
    }
  }
}
</script>
<style scoped lang="less">
.keyboard {
  width: 100%;
  margin: 0 auto;
  font-size: 18px;
  border-radius: 2px;
  padding-top: 0.5em;
  background-color: #e5e6e8;
  user-select: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 999;
  pointer-events: auto;
  p {
    width: 95%;
    margin: 0 auto;
    height: 45px;
    margin-bottom: 0.5em;
    display: flex;
    display: -webkit-box;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    i {
      display: block;
      margin: 0 1%;
      height: 45px;
      line-height: 45px;
      font-style: normal;
      font-size: 24px;
      border-radius: 3px;
      width: 44px;
      background-color: #fff;
      text-align: center;
      flex-grow: 1;
      flex-shrink: 1;
      flex-basis: 0;
      -webkit-box-flex: 1;
      &:active {
        background-color: darken(#ccc, 10%);
      }
    }
    .tab-top {
      width: 50px;
      margin: 0 1%;
      background: #cccdd0;
      color: #fff;
      font-size: 24px;
    }
    .key-delete {
      width: 50px;
      margin: 0 1%;
      color: #827f7f;
      background: #d7d7d8;
    }
    .tab-num {
      font-size: 18px;
      background: #dedede;
      color: #5a5959;
    }
    .tab-point {
      width: 20px;
    }
    .tab-blank {
      width: 80px;
      font-size: 12px;
      padding: 0 15px;
      color: #5a5959;
      line-height: 60px;
    }
    .tab-symbol {
      width: 20px;
      font-size: 18px;
    }
    .tab-enter {
      font-size: 30px;
      line-height: 54px;
    }
    &:nth-child(2) {
      width: 88%;
    }
  }
}
</style>

KeyInput.vue

<template>
  <div>
    <input type="text" ref="keyboard" v-model="inputValue" @focus="onFocus">
    <Keyboard :option="option" @keyVal="getInputValue" @close="option.show = false"></Keyboard>
  </div>
</template>
<script>
import Keyboard from '../components/Keyboard'
export default {
  components: {
    Keyboard
  },
  data() {
    return {
      option: {
        show: false,
        sourceDom: ''
      },
      inputValue: ''
    }
  },
  props: {},
  created() {},
  methods: {
    getInputValue(val) {
      if(val === 'delete'){
        this.inputValue = this.inputValue.slice(0,this.inputValue.length -1)
      }else{
        this.inputValue += val
      }
    },
    onFocus() {
      this.$set(this.option, 'show', true)
      this.$set(this.option, 'sourceDom', this.$refs['keyboard'])
    },
    //获取光标位置
    getCursorPosition() {
      let doc = this.$refs['keyboard']
      if (doc.selectionStart) return doc.selectionStart
      return -1
    },
    //设置光标位置 暂未实现
    setCursorPosition(pos) {
      let doc = this.$refs['keyboard']
      console.log(doc.setSelectionRange)
      doc.focus()
      doc.setSelectionRange(1,3)
    }
  }
}
</script>
<style lang="less" scoped>

</style>

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Vue 可以通过检测浏览器的 user agent(`navigator.userAgent`)来区分移动端PC 端。以下是一个简单的实现方法。 首先,在 Vue 组件中,可以使用通过 `mounted` 生命周期函数来监听页面的加载完成,然后访问全局的 `navigator.userAgent` 字符串: ```javascript mounted () { if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { // 移动端逻辑 // 例如,在移动端监听 touchstart 事件 document.addEventListener('touchstart', this.handleTouchEvent) } else { // PC 端逻辑 // 例如,在 PC 端监听 keydown 事件 document.addEventListener('keydown', this.handleKeyDown) } } ``` 在上述代码中,我们通过正则表达式检测 `navigator.userAgent` 字符串中是否包含移动设备的关键字,例如 `"Android"`、`"iPhone"` 等。如果匹配成功,则可以判断为移动端。否则,就可以判断为 PC 端。 在移动端逻辑中,可以监听移动端的触摸事件(如 `touchstart`、`touchmove`、`touchend` 等)来实现相应的键盘事件监听。在 PC 端逻辑中,则可以监听键盘事件(如 `keydown`、`keyup` 等)。 最后,需要在组件销毁时,也就是通过 `beforeDestroy` 生命周期函数,移除事件监听器,以免造成内存泄漏: ```javascript beforeDestroy () { if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { document.removeEventListener('touchstart', this.handleTouchEvent) } else { document.removeEventListener('keydown', this.handleKeyDown) } } ``` 通过以上逻辑,我们可以区分移动端PC 端,并实现相应的键盘事件监听。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑色咖啡 Ken

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值