基于vue封装触屏电脑键盘(keyboards)组件

先上效果图

 

 
1.支持光标选中位置,中间断点输入,删除等;

组件代码:

<template>
    <transition name="slide" mode="in-out">
        <div class="keyboards">
            <ul class="key_wrapper" >
                <li class="key_rows" v-for="(item,index) in keys" :key="index">
                    <span class="key_btn" v-for="(items, indexInner) in item" :key="indexInner" 
                        @click="getVal(items,$event)"
                        :class="{
                            capslock:((items[0] == 'capslock' && capslock) ? true : false),
                            shift:((items[0] == 'shift' && shift) ? true : false),
                            cap_btn:items[0] == 'capslock' ? true :false,
                            shift_btn:items[0] == 'shift' ? true :false,
                            del_btn:items[0] == 'delete' ? true :false,
                            submit_btn:items[0] == '完成' ? true :false,
                        }"
                    >{{items.constructor == Array ? (!capslock ? items[0] : items[1]) : ''}}</span>
                </li>
            </ul>
        </div>
    </transition>
</template>
<script>
/* 
    * handelChange 父组件 绑定输入改变事件
    *handelSave 父组件点击确定事件(处理键盘组件显示/隐藏等)
    *innerVal: 子组件props,接收当前input的内容
    *start: 子组件props,接受当前鼠标光标位置
*/ 
export default {
    props:['innerVal','start'], //初始值, 起始位置;
    data() {
        return {
            showKeys:true,
            keys:[
                [
                    ['`','~'],
                    ['1','!'],
                    ['2','@'],
                    ['3','#'],
                    ['4','$'],
                    ['5','%'],
                    ['6','^'],
                    ['7','&'],
                    ['8','*'],
                    ['9','('],
                    ['0',')'],
                    ['-', '_'],
                    ['=','+'],
                    ['delete','delete']
                ],
                [
                    ['q',"Q"],
                    ['w',"W"],
                    ['e',"E"],
                    ['r',"R"],
                    ['t',"T"],
                    ['y',"Y"],
                    ['u',"U"],
                    ['i',"I"],
                    ['o',"O"],
                    ['p',"P"],
                    ['[','{'],
                    [']','}']
                ],
                [
                    ['capslock','capslock'],
                    ['a','A'],
                    ['s','S'],
                    ['d','D'],
                    ['f','F'],
                    ['g','G'],
                    ['h','H'],
                    ['j','J'],
                    ['k','K'],
                    ['l','L'],
                    [';',':'],
                    ["'",'"'],
                    ['\\','|']
                ],
                [
                    // ['shift','shift'],
                    ['z','Z'],
                    ['x','X'],
                    ['c','C'],
                    ['v','V'],
                    ['b','B'],
                    ['n','N'],
                    ['m','M'],
                    [',','<'],
                    ['.','>'],
                    ['/','?'],
                    ['完成','完成']
                ]
            ],
            capslock:false, //默认大写
            shift:false,  //默认shift
            innerHTML:"", //输入的值
            tmpPoint:0, 
        }
    },
    watch:{
        innerVal(news){
            this.innerHTML = news;
        },
        start(news){
            this.tmpPoint = news;
        },
        innerHTML(news){
            this.$emit("handelChange",news)
        }
    },
    methods: {
        getVal(items,e){
            let val = items.constructor == Array ? items[0] : items; //当前选中的值
            if( val == 'capslock' ){
                this.capslock = ! this.capslock;
            }else if(val == 'shift'){
                this.shift = !this.shift;
            }else if(val == '完成'){
                this.$emit("handelSave")
            }else{
                let vals = e.target.innerHTML;
                let start_ = this.innerHTML.length >0  ? this.innerHTML.substr(0,this.tmpPoint) : "";
                let end = this.innerHTML.length > 0 ? this.innerHTML.substr(this.tmpPoint) : "";
                if( vals == 'delete'){
                    if(this.tmpPoint >=1  && start_.length > 0){
                        this.tmpPoint-=1;
                        this.innerHTML = this.innerHTML.slice(0,start_.length-1)+end;
                    }
                }else{
                    this.tmpPoint+=1;
                    this.innerHTML = start_+vals+end;
                }
            }
        }
    },
}
</script>
<style lang="scss">
    .slide-enter,
    .slide-leave-to {
        opacity: 0;
        transform:translateY(2rem);
    }
    .slide-enter-active,
    .slide-leave-active {
        transition: all .5s;
    }
    .keyboards{
        width: 100%;
        height: 2rem;
        background: #fff;
        position: absolute;
        bottom: 0px;
        .key_wrapper{
            height: 100%;
            width: 100%;
            .key_rows{
                text-align: center;
            }
        }
        .key_btn{
            user-select: none;
            cursor: pointer;
            padding:.1rem 0;
            width: .3rem;
            font-size: .14rem;
            display: inline-block;
            margin: .03rem;
            border: 1px solid #ccc;
        }
        .del_btn{
            width: .6rem;
        }
        .shift_btn{
            width: .4rem;
        }
        .cap_btn{
            width: .7rem;
        }
        .submit_btn{
            width: .4rem;
            background: rgb(44, 79, 175);
            color: #fff;
        }
        .capslock,.shift{
            background: rgb(44, 79, 175);
            color: #fff;
        }
    }
</style>



posted @ 2021-07-23 10:30  忧伤还是快乐i  阅读(285)  评论(0编辑  收藏  举报