7.从0做一个vue键盘组件

news2024/11/20 7:47:19

文章目录

  • 1. 从0做一个键盘组件
    • 1.1. 最终效果
    • 1.2. 分析
    • 1.3. 实现
    • 1.4. 如何引用

1. 从0做一个键盘组件

首先是why的问题:为什么需要做键盘组件?

我们目前可知的场景:

  1. 在新增账单的时候,需要用到键盘
  2. 在比如从账单列表页,进行行项目编辑某笔账单的时候,也需要用到键盘

如果都是每个vue页面自己写键盘的话,就比较尴尬了,回头需要优化的时候,就要多处维护。

所以,我们需要定义一个键盘组件。

1.1. 最终效果

或者是编辑的时候:

1.2. 分析

  1. 主要是显示:item_name账单类目名称、bill_money账单金额、账单日期选择、提交账单、删除账单
  2. 如果是新增账单,就不显示”删除账单“按钮;如果是编辑账单,展示”删除账单“按钮。

1.3. 实现

整体的键盘样式都比较简单,可以直接通过布局来绘制。

直接上代码:

<template>
	<view class="keyboardbox">
		<view style="display: flex; font-size: 50rpx; justify-content: space-between; padding: 20rpx 20rpx;">
			<view style="font-size: 40rpx;">{{item_name}}</view>
			<view color = '#bbb' >{{bill_money}}</view>
		</view>
		<u-input
		    placeholder="备注: 点击填写备注"
		    :border="true"
			v-model="bill_desc"
		    clearable
		></u-input>
		<view class="numkeyboard">
			<view class="num-area">
				<view class="row" v-for="(item,index) in numKeybordList" :key="index">
					<view class="item"
						v-for="(ite,idx) in item" hover-class="active" :hover-start-time="0"
						:hover-stay-time="5" :key="idx" @tap="input(ite)">{{ite}}</view>
				</view>
			</view>
			<view class="btn-area">
				<view :class="['item','dateChoose']" hover-class="active" :hover-start-time="0" :hover-stay-time="5"
					@tap="dateVal">
						<view class="uni-input">{{choosedDateShow}}</view>
				</view>
				<view :class="['item','del']" hover-class="active" :hover-start-time="0" :hover-stay-time="5"
					@tap="deleteVal">
					<u-icon name="arrow-leftward"></u-icon>
				</view>
				<view class="confirem item" hover-class="active" :hover-start-time="0" :hover-stay-time="5"
					@tap="submit">
					完成
				</view>
				<view v-if="add_or_update=='编辑账单'" class="deletebill item" hover-class="active" :hover-start-time="0" :hover-stay-time="5"
					@tap="deleteBill">
					删除账单
				</view>
			</view>
		</view>
	</view>
	
	<u-picker mode="time"
		:default-time="date_picker_date" 
		v-model="date_picker_show" 
		:params="date_picker_params"
		@confirm="date_pick_ok"
		>
	</u-picker>
	
	<!-- <u-modal v-model="showDeleteBillModal" :content="content" negative-top=500></u-modal> -->
</template>



<script setup>
	import {
		ref, defineProps, defineEmits, watch, defineModel, computed
	} from 'vue';
	import {onLoad,onUnload,onReachBottom,onShareAppMessage,onShareTimeline} from "@dcloudio/uni-app"
	
	
	
	onLoad((e)=>{
		
	});
	
	const add_or_update = defineModel("add_or_update", { type: String, default: '' });
	const bill_id = defineModel("bill_id", { type: String, default: '' });
	const item_name = defineModel("item_name", { type: String, default: '' });
	const bill_money = defineModel("bill_money", { type: String, default: '' });
	const bill_desc = defineModel("bill_desc", { type: String, default: '' });
	const date_picker_date = defineModel("date_picker_date", {type: String, default: ''})
	
	console.log(add_or_update.value);
	console.log(date_picker_date.value);
	console.log(bill_id.value);
		
	const numKeybordList = ref([  // 键盘数值
		[1, 2, 3],
		[4, 5, 6],
		[7, 8, 9],
		[0, '.']
	]);
	
	// 默认不显示时间选择组件。在点击了“今天”之后,可以进行选择其他日期
	const date_picker_show = ref(false);
	// 选择时间时候的时间选择组件,仅展示年月日
	const date_picker_params = ref({
		year: true,
		month: true,
		day: true,
		hour: false,
		minute: false,
		second: false
	});
	
	// 监听contentId
	// watch(()=>props.item_name,(newValue, oldValue)=>{
	// 	console.log(newValue);
	//    item_name.value = newValue
	// },{ deep: true, immediate:true})
	
	
	/**
	 * 按键
	 * @param {Object}
	 */
	// const clickInfo = () => {
	const input = (val) => {
	// input(val) {
		let money = bill_money.value;
		if (money.length >= 10) {
			uni.showToast({
				title: '金额过大',
				icon: 'error'
			})
			return;
		}
		let arr = money.split('.');
		if (money == '0.00' && val != null) {
			money = val.toString();
		} else {
			let arr = money.split('.');
			if (val == '.' && arr.length > 1) {
		
			} else if (arr.length <= 1 || (arr.length > 1 && arr[1].length <= 1)) {
				if (money == '0' && val != '.') {
					money = val.toString();
				} else if (money != '0' || val != '0')
					money += val;
			}
		}
		bill_money.value = money;
		
	};
	/**
	 * 删除
	 */
	const deleteVal = () => {
	// deleteVal() {
		let money = bill_money.value; 
		console.log(money.length);
		if (money != '0.00' && money.length > 0)
			money = money.substring(0, money.length - 1)
		if (money.length <= 0)
			money = '0.00';
			
		bill_money.value = money;
	};
	const date_pick_ok = (callback_data) => {
	// date_pick_ok(callback_data) {
		date_picker_date.value = callback_data.year + '-' + callback_data.month + '-'  + callback_data.day;
		console.log('选择了:' + date_picker_date.value);
	};
	
	const dateVal = () => {
		date_picker_show.value = true;
	};
	
	const emit = defineEmits(['submit', 'deleteBill']);
	
	const submit = () => {
		emit(
		'submit',
		{
			bill_money: bill_money.value,
			bill_desc: bill_desc.value,
			date_picker_date: date_picker_date.value
		},
		(res)=>{
			//回调函数的方法体.处理自己的业务.
			console.log("获取到父组件执行结果的回调");
			console.log(res);
		 }
		);
	};
	
	const deleteBill = () => {
		
		uni.showModal({
			title: '提示',
			content: '确定要删除此账单吗?',
			success: function (res) {
				if (res.confirm) {
					console.log('用户点击确定');
					emit(
					'deleteBill',
					{
						bill_id: bill_id.value
					},
					(res)=>{
						//回调函数的方法体.处理自己的业务.
						console.log("获取到父组件执行结果的回调");
						console.log(res);
					 }
					);
				} else if (res.cancel) {
					console.log('用户点击取消');
				}
			}
		});
		
		
		
	};
	
	const getTodayDateTime = () => {
		var date = new Date();
		var Y = date.getFullYear() + '-';
		var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1):date.getMonth()+1) + '-';
		var D = (date.getDate()< 10 ? '0'+date.getDate():date.getDate())+ ' ';
		var h = (date.getHours() < 10 ? '0'+date.getHours():date.getHours())+ ':';
		var m = (date.getMinutes() < 10 ? '0'+date.getMinutes():date.getMinutes()) + ':';
		var s = date.getSeconds() < 10 ? '0'+date.getSeconds():date.getSeconds();
		return Y+M+D+h+m+s;
	};
	
	// 一个计算属性 ref
	const choosedDateShow = computed(() => {
		if (date_picker_date.value == getTodayDateTime().substring(0, 10)) {
			return '今天';
		}
		else {
			return date_picker_date.value;
		}
	})
	
</script>

<style lang="scss">
.keyboardbox {
		width: 100%;
		position: absolute;
		left: 0;
		bottom: 0;
		background-color: #FFFFFF;
	
		.numkeyboard {
			height: 432rpx;
			display: flex;
			background-color: #ebedf0;
	
			.btn-area {
				width: 180rpx;
				height: 100%;
				display: flex;
				flex-direction: column;
	
				.item {
					width: 100%;
					display: flex;
					justify-content: center;
					align-items: center;
					flex-grow: 1;
				}
	
				.del {
					background-color: #ebedf0;
					color: #333;
	
					&.active {
						background-color: #f1f3f5;
					}
				}
	
				.confirem {
					background-color: #4fae70;
					color: #FFFFFF;
	
					&.active {
						background-color: #4fae70;
					}
				}
				
				.deletebill {
					background-color: #e94d26;
					color: #333;
				}
				
				.dateChoose {
					background-color: #f9db56;
					color: #2d2d2d;
						
					&.active {
						background-color: #f9db56;
					}
				}
			}
	
			.num-area {
				flex-grow: 1;
				display: flex;
				flex-wrap: wrap;
	
				.row {
					width: 100%;
					height: 25%;
					display: flex;
					margin-top: 1px;
	
					.item {
						flex-grow: 1;
						height: 100%;
						display: flex;
						justify-content: center;
						align-items: center;
						background-color: #FFFFFF;
						border-right: 1px solid #ebedf0;
						width: 33.33%;
	
						&.active {
							background-color: #ebedf0;
						}
	
						&.z {
							flex-grow: 2;
							width: 66.66%;
						}
	
						&.disabled {
							background: #FFFFFF;
							color: #B9B9B9;
						}
					}
				}
	
			}
		}
	}
</style>

1.4. 如何引用

我们选择在父组件里面,通过一个u-popup来包裹此键盘组件,并在显示之前,把要传递进去显示的数据用v-model进行绑定:

  • 如果是添加账单的场景:父组件传值给子组件;子组件要调用父组件的submit方法;子组件要知道父组件submit方法的执行结果。
<u-popup v-model="popup_show" mode="bottom" border-radius="14" height="600rpx">
		<keyboard-info 
		:item_name="item_name" 
		:bill_money="bill_money" 
		:bill_desc="bill_desc"
		:date_picker_date="date_picker_date"
		:add_or_update="'添加账单'"
		@submit="submit"
		>
		</keyboard-info>
	</u-popup>
// 上面的item_name、bill_money、bill_desc、date_picker_date要自行处理赋值。
selectItem(index) {
  this.bill_money = '0.00';// 点击弹出的金额默认还原为0
  this.bill_desc = '';// 理由同上
  this.select_item = index;
  this.popup_show = true;  // 展示u-popup,也就能展示出来键盘子组件了。
  if (this.current_type == 0) {
    this.item_name = this.expenditure_list[index-1].text
    this.item_img_path = this.expenditure_list[index-1].icon
    this.item_id = this.expenditure_list[index-1].id
  }
  else {
    this.item_name = this.income_list[index-1].text
    this.item_img_path = this.income_list[index-1].icon
    this.item_id = thisincome_list[index-1].id
  }
},
// submit方法,主要是用来给键盘组件在点击键盘的”提交“按钮时,将键盘组件录入的数据回传到父组件的submit方法中
// 这里要再说一下callback参数,其实是键盘组件为了获取到父组件执行了submit方法之后的返回值,以便在成功执行操作之后,将键盘隐藏或引导页面跳转
submit(data, callback) {
  console.log('收到键盘子组件触发submit方法');
  console.log(data);
  if (this.direction == '支出') {
    data.bill_money = -data.bill_money;
  }
  // console.log('bill_add.vue的 submit() 方法被调用');
  let bill_detail = {
    bill_id: this.direction + this.getTodayDateTime(),
    direction: this.direction,
    year: parseInt(this.date_picker_date.substring(0, 4)),
    month: parseInt(this.date_picker_date.substring(5,7)),
    day: parseInt(this.date_picker_date.substring(8,10)),
    week: this.getWeek(this.date_picker_date),
    item_name: this.item_name,
    item_img_path: this.item_img_path,
    item_id: parseInt(this.item_id),
    add_time: this.getTodayDateTime(),
    update_time: this.getTodayDateTime(),
    // 下面3个,是从键盘组件回调来的值
    bill_desc: data.bill_desc,
    bill_date: data.date_picker_date,
    bill_money: parseFloat(data.bill_money)
  }
  console.log(bill_detail);
  callback(true);
},
  • 如果是编辑账单的场景

    <u-popup v-model="popup_show" mode="bottom" border-radius="14" height="600rpx">
    			<keyboard-info 
    			:item_name="item_name" 
    			:bill_money="bill_money" 
    			:bill_desc="bill_desc"
    			:date_picker_date="date_picker_date"
    			:add_or_update="'编辑账单'"
    			:bill_id="bill_id"
    			@submit="submit"
    			@deleteBill="deleteBill"
    			>
    			</keyboard-info>
    		</u-popup>
    

    跟之前的分析是类似的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1686984.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年 电工杯 (B题)大学生数学建模挑战赛 | 大学生平衡膳食食谱的优化设计 | 数学建模完整代码解析

DeepVisionary 每日深度学习前沿科技推送&顶会论文&数学建模与科技信息前沿资讯分享&#xff0c;与你一起了解前沿科技知识&#xff01; 本次DeepVisionary带来的是电工杯的详细解读&#xff1a; 完整内容可以在文章末尾全文免费领取&阅读&#xff01; 问题1&…

【Python自动化测试】:Unittest单元测试与HTMLTestRunner自动生成测试用例的好帮手

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;unittest编写测试用例&#x1f680;unittest测…

49 序列化和反序列化

本章重点 理解应用层的作用&#xff0c;初识http协议 理解传输层的作用&#xff0c;深入理解tcp的各项特性和机制 对整个tcp/ip协议有系统的理解 对tcp/ip协议体系下的其他重要协议和技术有一定的了解 学会使用一些网络问题的工具和方法 目录 1.应用层 2.协议概念 3. 网络计…

awesome-ai4s 现已开源!超全 AI for Science 学术论文与数据资源汇总,持续更新ing

2018 年中国科学院院士鄂维南提出「AI for Science」概念&#xff0c;强调利用 AI 学习科学原理、创造科学模型来解决实际问题。同年&#xff0c;AlphaFold 崭露头角&#xff0c;从 43 种蛋白质中准确预测出了 25 种蛋白质结构。2021 年&#xff0c;AlphaFold 2 开源并预测了 9…

缓存降级

当Redis缓存出现问题或者无法正常工作时,需要有一种应对措施,避免直接访问数据库而导致整个系统瘫痪。缓存降级就是这样一种机制。 主要的缓存降级策略包括: 本地缓存降级 当Redis缓存不可用时,可以先尝试使用本地进程内缓存,如Guava Cache或Caffeine等。这样可以减少对Redis…

OpenLayers中实现对ImageStatic图层的扩展以支持平铺WrapX功能

地图平铺技术概述 地图平铺&#xff08;Tiling&#xff09;是一种将大尺寸地图数据分割成小块&#xff08;瓦片&#xff09;的技术&#xff0c;这在地图服务中非常常见。它使得地图数据能高效加载和展示&#xff0c;尤其适合网络环境。通过仅加载当前视图窗口所需的地图瓦片&a…

Qt官方示例---opengl

文件相对路径&#xff1a;Examples\Qt-5.9.1\opengl 2dpainting cube computegles31 contextinfo hellogl2 hellowindow paintedwindow qopenglwidget qopenglwindow textures threadedqopenglwidget

Rabbitmq 搭建使用案例 [附源码]

Rabbitmq 搭建使用案例 文章目录 RabbitMQ搭建docker 代码golang生产者消费者 可视化消费进度 RabbitMQ搭建 docker docker run -d --hostname rabbitmq --name rabbitmq -e RABBITMQ_DEFAULT_USERadmin -e RABBITMQ_DEFAULT_PASSadmin -e RABBITMQ_DEFAULT_VHOSTmy_vhost -e…

重组蛋白表达系统优缺点对比|卡梅德生物

重组蛋白是现代生物技术中不可或缺的一部分&#xff0c;它们广泛应用于药物开发、研究工具和工业酶的生产。根据目标蛋白的特性和所需的修饰&#xff0c;可以选择不同的表达系统。下文罗列一下四个主要蛋白表达系统的优缺点&#xff1a; 1. 原核表达系统&#xff08;如大肠杆菌…

【QT实战】汇总导航

✨Welcome 大家好&#xff0c;欢迎来到瑾芳玉洁的博客&#xff01; &#x1f611;励志开源分享诗和代码&#xff0c;三餐却无汤&#xff0c;顿顿都被噎。 &#x1f62d;有幸结识那个值得被认真、被珍惜、被捧在手掌心的女孩&#xff0c;不出意外被敷衍、被唾弃、被埋在了垃圾堆…

深度学习之基于Tensorflow卷积神经网络(CNN)实现猫狗识别

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 在人工智能和深度学习的热潮中&#xff0c;图像识别是一个备受关注的领域。猫狗识别作为图像识…

Milvus的内存索引

简介&#xff1a; 这篇文章主要介绍milvus支持的各种内存索引&#xff0c;以及它们最适用的场景&#xff0c;还有用户为了获得更好的搜索性能可以配置的参数。 索引是有效组织数据的过程&#xff0c;它的主要角色是在大的数据集中显著的加速耗时的查询从而有效的进行相似搜索…

【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)

最终效果 文章目录 最终效果前言素材模拟绳子钩子来回摆动发射回收钩子方法发射钩子回收钩子勾取物品随机生成物品其他源码完结 前言 在游戏发展史上&#xff0c;有些游戏以其简单而耐玩的特性&#xff0c;深深地烙印在了玩家的记忆中。《黄金矿工》就是其中之一&#xff0c;它…

SpringBootWeb 篇-深入了解 Mybatis 删除、新增、更新、查询的基础操作与 SQL 预编译解决 SQL 注入问题

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Mybatis 的基础操作 2.0 基础操作 - 环境准备 3.0 基础操作 - 删除操作 3.1 SQL 预编译 3.2 SQL 预编译的优势 3.3 参数占位符 4.0 基础操作 - 新增 4.1 主键返回…

每周节省7800万工时!ChatGPT等成美国降本增效利器

5月23日&#xff0c;全球最大教育、商业出版社之一的Pearson plc在官网发布了&#xff0c;ChatGPT等生成式AI如何帮助人们提升工作效率节省时间的深度研究报告。 该报告一共分析了美国、英国、澳大利亚、巴西和印度5个国家。到2026年&#xff0c;美国节省的时间最多&#xff0…

面试准备-项目【面试准备】

面试准备-项目【面试准备】 面试准备自我介绍&#xff1a;项目介绍&#xff1a; 论坛项目功能总结简介数据库表设计注册功能登录功能显示登录信息功能发布帖子评论私信点赞功能关注功能通知搜索网站数据统计热帖排行缓存 论坛项目技术总结Http的无状态cookie和session的区别为什…

GIS竞赛指南

全国大学生GIS应用技能大赛 全国大学生GIS应用技能大赛 主办单位:中国地理信息产业协会、中国地理学会 协办单位&#xff1a;广州大学(2023年) 参赛要求&#xff1a;每个学校一支队伍&#xff0c;限在读本科生组队不超过4人&#xff0c;指导老师不超过2人&#xff0c;一般学…

三磷酸肌醇(IP3)为细胞内信号转导分子 在医药、科研领域应用前景广阔

三磷酸肌醇&#xff08;IP3&#xff09;为细胞内信号转导分子 在医药、科研领域应用前景广阔 三磷酸肌醇又称为肌醇三磷酸&#xff0c;简称InsP3或IP3&#xff0c;是一种小信号分子&#xff0c;由磷脂酶C催化磷脂酰肌醇-4,5-二磷酸水解产生的&#xff0c;水解后剩下的甘油二酯停…

异众比率(variation ratio)

异众比率&#xff08;variation ratio&#xff09;是指非众数组的频数占总频数的比率&#xff0c;其计算公式为: 其中&#xff0c;为众数组的频数。 异众比率主要用于衡量众数对一组数据的代表程度。异众比率越大&#xff0c;说明非众数组的频数占总频数的比重越大&#xff0…