前端歌谣-第一百一十课-Vue3实现简单数字键盘效果

前言

大家好 我是歌谣 今天给大家带来vue3的功能关于键盘的实现

封装的小组件代码

<template>
    <div class="key-container">
        <div class="keyboard" @click.stop="handleKeyPress">
            <div class="key-row">
                <div class="cell-box">
                    <div class="key-cell" data-num="1">1</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="2">2</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="3">3</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="4">4</div>
                </div>
            </div>
            <div class="key-row">
                <div class="cell-box">
                    <div class="key-cell" data-num="5">5</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="6">6</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="7">7</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="8">8</div>
                </div>
            </div>
            <div class="key-row">
                <div class="cell-box">
                    <div class="key-cell" data-num="9">9</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="0">0</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="C">清空</div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num="S">报工</div>
                </div>
            </div>
            <!-- <div class="key-row">
                 <div class="cell-box">
                    <div class="key-cell" data-num=".">.</div>
                </div> 
                <div class="cell-box">
                    <div class="key-cell" data-num="0">0</div>
                </div>
                 <div class="cell-box">
                    <div class="key-cell key-delete" data-num="C">删除</div>
                </div> 
                <div class="cell-box">
                    <div class="key-cell" data-num></div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num></div>
                </div>
                <div class="cell-box">
                    <div class="key-cell" data-num></div>
                </div>
            </div> -->
            <!-- <div class="key-right-clear">
                <div class="key-clear" data-num="C">清空</div>
            </div>
            <div class="key-right-confirm">
                <div class="key-confirm" data-num="S">报工</div>
            </div> -->
        </div>
    </div>
</template>
<script setup>
import { ref } from 'vue'
const props = defineProps({
    //默认传入的数据线
    clickTime: {
        type: Number,
    },
    //默认传入的索引
    fatherNum: {
        type: Number,
        default: 0
    }
});
const emit = defineEmits(["clearEvent", "deleteEvent", "numberEvent", "confirmEvent"])
const num = ref(0)
const click = ref(0)
const { fatherNum, clickTime } = props
const handleKeyPress = (e) => {
    console.log(e, "is")
    const number = e.target.dataset.num;
    console.log(number, "is")
    // 不同的按键处理逻辑
    // num为空,直接返回
    if (!number) return;
    switch (String(number)) {
        // 删除键
        case "D":
            handleDeleteKey();
            break;
        // 清空键
        case "C":
            handleClearKey();
            break;
        // 确认键
        case "S":
            handleConfirmKey();
            break;
        default:
            handleNumberKey(number);
            break;
    }
}
console.log(fatherNum, "fatherNum is")
const handleDeleteKey = () => {
    console.log(fatherNum, "fatherNum is")
    num.value = fatherNum; // 这一步是为了让this.num能及时接收this.fatherNum的值,解决第二行输入后去删除第一行值出现的bug
    const S = num.value;
    console.log(S, "S is")
    // if (!S.toString()) return false;
    if (!S.toString().length) return false;// 如果没有输入(或者长度为0),直接返回
    // 否则删除最后一个
    num.value = S.toString().substring(0, S.toString().length - 1);
    console.log(num.value, "value is")
    emit("deleteEvent", num); //把删除处理后了的值返回给父组件
}
// 处理清空键
const handleClearKey = () => {
    num.value = 0; // 清空就赋值一个‘’,然后返回给父组件
    emit("clearEvent", num);
}
// 处理数字
const handleNumberKey = (number) => {
    // 确保处理的this.num是父组件传入的this.fatherNum
    num.value = fatherNum;
    click.value = clickTime;
    const S = num.value; // 拿到父组件点击的那个输入框的值
    //   第一次不能输入.
    if (click == 1) {
        if (number == ".") return;
    }
    //前提是并非刚点击了input
    if (click != 1) {
        // 若this.num有且只有一位数并且是0,则输入的不是.,就返回
        if (S && S.length == 1 && S[0] == 0 && number != ".") return;
        if (S) {
            let index = S.toString().indexOf(".");
            // 如果存在.,则不能再次输入.
            if (index > -1 && number == ".") return;
            //   小数位数不能超过2位
            if (S && index > -1 && S.length - 2 > index) return;
        }
    }
    if (!S) {
        //如果是首次输入,则原有的this.num是undefined,不需要拼接上
        num.value = `${number}`;
    } else {
        num.value = `${S}${number}` // 在原有的基础上将点击的那个数字按键的数字加在原有数字字符串末尾,此处是为删除提供数据
    }
    //   此处不能使用正则表达式判断

    emit("numberEvent", number); // 注意传的是点击的那个数字字符串,不是处理后的整个数字字符串
}
// 确认键
const handleConfirmKey = () => {
    // 这一步是为了解决一进页面,input框内有值,直接点确认出现数据情况,再次点数据出现undefined问题(如果没有该赋值,this.num为undefined)
    // num.value = fatherNum;
    // const S = num.value;
    // // 如果输入的数字最后一位是.,则删除
    // if (S) {
    //     let index = S.toString().indexOf(".");
    //     if (index == S.length - 1) {
    //         num.value = S.substring(0, S.length - 1);
    //     }
    // }

    emit("confirmEvent");
}


</script>

<style lang="less" scoped>
.key-container {
    width: 100%;
    height: 3.8rem;
    display: flex;
    display: -webkit-flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    font-weight: bold;
    color: rgba(51, 51, 51, 0.85);

    .keyboard {
        position: fixed;
        bottom: 0;
        left: 0;
        width: 100%;
        background-color: #fff;
        padding: 0.05rem;
        background: rgba(240, 240, 240);
        box-sizing: border-box;

        .key-row {
            display: flex;
            display: -webkit-flex;
            position: relative;
            line-height: 1rem;

            &::before {
                content: "";
                position: absolute;
                left: 0;
                top: 0;
                right: 0;
                height: 1px;
                color: #d5d5d6;
                -webkit-transform-origin: 0 0;
                transform-origin: 0 0;
                -webkit-transform: scaleY(0.5);
                transform: scaleY(0.5);
            }
        }

        .cell-box {
            font-size: 0.42rem;
            font-weight: bold;
            flex: 1;
            -webkit-box-flex: 1;
            text-align: center;
            position: relative;
            padding: 0.05rem;
            box-sizing: border-box;

            &::after {
                content: "";
                position: absolute;
                overflow: hidden;
                top: 0;
                right: 0;
                bottom: 0;
                height: 200%;
                color: #d5d5d6;
                -webkit-transform-origin: 0 0;
                transform-origin: 0 0;
                -webkit-transform: scaleY(0.5);
                transform: scaleY(0.5);
            }

            &:nth-last-child(1)::after {
                border-right: 0;
            }
        }

        .key-cell {
            background: #fff;
            border-radius: 0.1rem;
        }

        .key-delete {
            font-size: 0.38rem;
        }

        .key-right-confirm {
            font-size: 0.38rem;
            padding: 0.05rem;
            position: absolute;
            text-align: center;
            height: 2.1rem;
            width: 23%;
            line-height: 2.1rem;
            background: rgba(240, 240, 240);
            z-index: 5;
            right: 0.05rem;
            bottom: 0.05rem;
        }

        .key-right-clear {
            font-size: 0.38rem;
            padding: 0.05rem;
            position: absolute;
            text-align: center;
            height: 2.1rem;
            width: 23%;
            line-height: 2.1rem;
            background: rgba(240, 240, 240);
            z-index: 5;
            right: 0.05rem;
            top: 0.05rem;
        }

        .key-confirm {
            border-radius: 0.1rem;
            background: #1561b3;
            color: #fff;
        }

        .key-clear {
            border-radius: 0.1rem;
            background: #fff;
        }
    }
}</style>

父组件使用

<Numberkey v-show="keyShow" v-model:fatherNum="formState.user[type]" :clickTime="clickTime" @confirmEvent="confirmEvent"
    @numberEvent="numberEvent" @clearEvent="clearEvent" @deleteEvent="deleteEvent"></Numberkey>

方法和变量

const formState = ref({
  user: {
    planned: 0,
    qualified: 0,
    unqualified: 0,
    scrap: 0,
    teamcode:0
  },
});
const numberEvent = (res) => {
  console.log(res, "res is")
  formState.value.user[`${type.value}`] =
    clickTime.value == 1
      ? `${res}`
      : `${formState.value.user[`${type.value}`]}${res}`;
  //此处设置是为了让键盘点击的值能立马显示在input框中,如没有此设置,只有点击确认键盘隐藏时才会显示数据
  keyShow.value = false;
  keyShow.value = true;
  clickTime.value = 2;
}
const handledata = (datatype) => {
  keyShow.value = true;
  type.value = datatype
}
// 点击确认键
const confirmEvent = (res) => {
  // console.log(formState, type, res, "type is")
  // formState.value.user[`${type.value}`] = res.value;
  // 点击确认,收起键盘
  numberNew.value++
  if (numberNew.value > baseArray.length - 1) {
    router.push({
      name: "index"
    });
  } else {
    router.push({
      name: baseArray[0].route
    });
  }

}
const clearEvent = (res) => {
  formState.value.user[`${type.value}`] = res.value; // 清除,子组件传过来的是‘’
  // 此处设置是为了让键盘点击的值能立马显示在input框中,如没有此设置,只有点击确认键盘隐藏时才会显示数据
  keyShow.value = false;
  keyShow.value = true;
}
// 点击删除键
const deleteEvent = (res) => {
  formState.value.user[`${type.value}`] = res.value;
  // 此处设置是为了让键盘点击的值能立马显示在input框中,如没有此设置,只有点击确认键盘隐藏时才会显示数据
  keyShow.value = false;
  keyShow.value = true;
}

运行结果

在这里插入图片描述

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 外卖项目的前后端分离是指将项目的前端部分和后端部分进行分离开发,前端使用Vue框架,后端使用Spring Boot框架。 前端使用Vue框架可以提供良好的用户界面和交互体验。Vue具有组件化的特点,使得前端开发更加模块化和可维护。同时,Vue的数据绑定和响应式设计可以帮助实现快速更新页面的功能。通过Vue,用户可以方便地浏览外卖项目的菜单、下单、支付等操作,提升用户的使用体验。 后端使用Spring Boot框架可以提供强大的后台支持。Spring Boot是一种轻量级的Java框架,可以快速搭建和部署项目,减少开发的复杂度。使用Spring Boot,开发人员可以方便地实现外卖项目的后台逻辑,例如订单的处理、菜单的管理、支付的接口等。同时,Spring Boot集成了许多常用且可靠的开源库,为项目提供了高效、稳定的基础设施。 前后端分离的优势在于前端和后端可以并行开发,提高开发效率。前端和后端之间通过定义接口进行通信,降低了耦合度,灵活性更强。同时,单独部署前端和后端也可以提高项目的可维护性和可扩展性。例如,当需要添加新的功能或修改现有功能时,只需要修改相应的前端或后端代码,而不会影响到整个项目。 总之,外卖项目的前后端分离以及使用Vue和Spring Boot框架的设计选择,可以帮助实现一个高效、稳定、可扩展的外卖平台。 ### 回答2: 外卖项目采用前后端分离的架构,前端使用Vue框架,后端采用Spring Boot框架。 前端使用Vue框架可以实现用户界面的可视化设计和交互体验。Vue框架具有简单易用、灵活可扩展、高效性能等特点,适用于构建复杂的单页面应用(SPA)。通过Vue框架,可以实现用户注册、登录、浏览菜单、购物车管理、订单处理等功能的前端设计和开发。前端通过调用后端接口,获取后端处理的数据,并将数据展示在用户界面上。 后端使用Spring Boot框架可以实现业务逻辑的处理和数据存储。Spring Boot框架提供了快速构建、简化配置和集成多种功能的特性,适用于快速开发和维护可靠的应用程序。通过Spring Boot框架,可以处理用户注册、登录验证、菜单管理、订单处理等业务逻辑,并与数据库进行交互,存储与外卖项目相关的数据。后端还需要提供RESTful接口,供前端调用和交互。 前后端分离架构的好处是可以实现前端与后端的解耦,提高开发效率和维护性。前端和后端可以同时进行开发,并可采用不同的技术栈,使得团队成员能够专注于自己的领域。前后端分离还可以实现多端复用,例如可以用同一组后端接口提供给Web端和移动端调用。 总的来说,外卖项目采用前后端分离的架构,借助Vue和Spring Boot框架实现了用户界面的展示和交互以及业务逻辑的处理和数据存储,从而使得项目开发更加高效和可维护。 ### 回答3: 外卖项目采用前后端分离的架构,前端使用Vue.js框架进行开发,后端使用Spring Boot框架进行开发。 前端使用Vue.js框架的原因是因为Vue.js具有简洁、高效、灵活的特点,能够轻松构建交互式的用户界面。Vue.js还拥有一套完整的生态系统,能够方便地进行组件化开发,并提供了强大的工具来处理数据和状态的变化。 后端使用Spring Boot框架的原因是因为Spring Boot是一个简化了Spring开发的微框架,能够快速构建可独立运行的、生产级的应用。Spring Boot提供了大量的开箱即用的特性,如自动配置、快速开发等,能够极大地提高开发效率。 在外卖项目中,前端负责用户界面的展示和交互逻辑的实现前端通过Vue.js进行组件化开发,将页面拆分为多个可复用的组件,提高开发效率和代码维护性。前端还通过Vue.js提供的路由功能,实现不同页面之间的跳转和导航。同时,前端还与后端通过HTTP协议进行通信,获取后端提供的数据和服务,并将其展示给用户。 后端负责处理前端发送的请求,并根据业务逻辑进行相应的处理,最终返回数据给前端。后端还负责与数据库交互,对数据进行增删改查操作。后端使用Spring Boot提供的RESTful风格的API,能够轻松构建出符合规范的接口。同时,后端还可以利用Spring Security进行权限管理,确保只有具备相应权限的用户才能访问特定的接口。 综上所述,外卖项目采用前后端分离的架构,前端使用Vue.js框架进行开发,后端使用Spring Boot框架进行开发,能够提高开发效率和代码的可维护性,同时还能够满足用户对于界面交互和数据操作的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值