vue 自定义键盘实现,根据input 定位

需求:

项目里面有很多的input 输入框,由于系统自带的键盘不满足需求,所以需要自定义键盘,并且在输入框focus 的时候键盘自动显示在下面。

该插件只实现了功能,样式需自己调试

本例解决了页面滚动键盘跟随滚动的问题,具体逻辑可自行了解

首先需要一个自定义键盘组件 cuskeyboard 如下:

<template>
    <div class="keyboardcon" v-if="isShowKeyBoard">
        <div class="number">
            <div
                    :class="active==index?'numberitem changecolor':'numberitem'"
                    v-for="(item,index) in lists"
                    :key="index"
                    @click.stop="choosekey(item,index)"
            >
                {{item.label}}
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'cuskeyboard',
        data() {
            return {
                lists: [{
                    value: '+',
                    label: '+'
                }, {
                    value: 1,
                    label: '1'
                }, {
                    value: 2,
                    label: '2'
                }, {
                    value: 3,
                    label: '3'
                }, {
                    value: '-',
                    label: '-'
                }, {
                    value: 4,
                    label: '4'
                }, {
                    value: 5,
                    label: '5'
                }, {
                    value: 6,
                    label: '6'
                },
                    {
                        value: 'du',
                        label: 'du'
                    }, {
                        value: 7,
                        label: '7'
                    }, {
                        value: 8,
                        label: '8'
                    }, {
                        value: 9,
                        label: '9'
                    },
                    {
                        value: 'V',
                        label: 'V'
                    },
                    {
                        value: 0,
                        label: '0'
                    }, {
                        value: '.',
                        label: '.'
                    }, {
                        value: 'delete',
                        label: 'delete'
                    }
                ],
                // num: [],
                active: null,
            }
        },
        props: {
            // 是否显示
            isShowKeyBoard: {
                type: Boolean,
                default: false
            },
            // 默认值
            currValue: {
                type: String,
                default: ''
            },
        },
        computed: {
            num() {
                return this.currValue.split('')
            }
        },
        methods: {
            // 拿到点击的那个键的值
            choosekey(item, index) {
                this.active = index;
                setTimeout(() => {
                    this.active = null;
                }, 100);
                if (item.label === 'delete') {
                    this.num.splice(this.num.length - 1, this.num.length)
                    this.$emit('changekey', this.num);
                } else {
                    this.num.push(item.label);
                    this.$emit('changekey', this.num);
                }
            },
        },
        mounted() {
        }
    }
</script>

<style lang="less" scoped>
    .cuskeyboard {
        width: 100%;
        z-index: 999;
    }

    .keyboardcon {
        position: absolute;
        background-color: #1c6ca1;
        width: 100%;
    }

    .keyboardcon .number {
        width: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-wrap: wrap;
    }

    .keyboardcon .number .numberitem {
        height: 2.64533333rem;
        box-sizing: border-box;
        border-top: 4px solid #F4F4F4;
        border-right: 4px solid #F4F4F4;
        width: 25%;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .changecolor {
        background-color: #D7D7D7;
    }
</style>

注意:

             单个输入框引用时

           1)@focus 的时候,要把该输入框绑定的属性名传出去

           2)需要设置class为 'KeyboardClass'

           3)需要设置ref 属性为 该输入框 v-model 的属性名

             多个输入框引用时  v-for 的情况 

           1)@focus  时需要把 当前输入框的 index 和 绑定的属性名 联合起来传出去 ,本例为 

`${index}--a`

           2)ref 的设置同上 `${index}--a`

           3)同样设置class 为 'KeyboardClass'

 在需要用的地方引入插件;代码如下:

<template>
    <div class="derails-info"
         @click.capture="handleClick"
         style="height:100vh;overflow-y: auto;position: relative">
        <div style="height: 100px">

        </div>
        <el-input v-model="form.input1" readonly ref="input1" class="KeyboardClass"
                  @focus="((e)=>handleFocus(e,'input1'))" placeholder="请输入内容"></el-input>

        <el-input v-model="form.input2" readonly ref="input2" class="KeyboardClass"
                  @focus="((e)=>handleFocus(e,'input2'))" placeholder="请输入内容"></el-input>

        <el-input
                v-for="(item,index) in arr" :key="index"
                v-model="item.a" readonly
                class="KeyboardClass"
                :ref="`${index}--a`"
                @focus="((e)=>handleFocus(e,`${index}--a`))" placeholder="请输入内容"></el-input>
        <Keyboard
                :style="keyboardStyle"
                :currValue="currValue"
                :isShowKeyBoard="isShowKeyBoard"
                @changekey="changekey"
        ></Keyboard>
        <div style="height: 800px">

        </div>
    </div>

</template>

<script>
    import Keyboard from '../components/cuskeyboard';

    export default {
        name: "TabDetails",
        data() {
            return {
                // 是否显示键盘
                isShowKeyBoard: false,
                currValue: '',
                form: {
                    input1: '',
                    input2: '',
                },
                arr: [{
                    a: ''
                }, {
                    a: ''
                }],
                key: '',
                keyboardStyle: {
                    position: 'absolute',
                    left: '',
                    top: ''
                }
            }
        },
        methods: {
            handleClick(e) {
                if (e.target.className === 'el-input__inner' &&
                    e.target.offsetParent.className.indexOf('KeyboardClass') !== -1) {
                    this.isShowKeyBoard = true
                } else {
                    this.isShowKeyBoard = false
                }
            },
            changekey(value) {
                let val = value.join(""); // 将拿到的值拼接
                // 代表为动态ref 绑定的是数组对象
                let splitArr = this.key.split('--')
                if (splitArr.length > 1) {
                    this.arr[splitArr[0]][splitArr[1]] = val
                    this.$refs[this.key][0].focus()
                } else {
                    this.form[this.key] = val;
                    this.$refs[this.key].focus()
                }
            },
            getDistanceOfLeft(obj) {
                let left = 0;
                let top = 0;
                while (obj) {
                    left += obj.offsetLeft;
                    top += obj.offsetTop;
                    obj = obj.offsetParent;
                }
                return {
                    left: left,
                    top: top
                };
            },
            handleFocus(e, key) {
                this.isShowKeyBoard = true
                this.keyboardStyle.left = this.getDistanceOfLeft(e.target).left + 'px'
                this.keyboardStyle.top = this.getDistanceOfLeft(e.target).top + 40 + 'px'
                this.key = key
                let splitArr = this.key.split('--')
                if (splitArr.length > 1) {
                    this.currValue = this.arr[splitArr[0]][splitArr[1]]
                } else {
                    this.currValue = this.form[this.key]
                }
            }
        },
        components: {
            Keyboard
        }
    }
</script>

<style lang="less" scoped>

</style>

效果图如下:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值