uniapp-vue3来实现一个金额千分位展示效果

前言:

        uniapp-vue3来实现一个金额千分位展示效果

实现效果:

实现目标:

1、封装组件,组件内部要实现,

  • input输入金额后,聚焦离开后,金额以千分位效果展示,
  • 聚焦后展示大写金额的弹框
  • 随时写的内容,可以用v-model传输给父级
  • 金额要有最大值,还要只能输入数字,小数后只能有2位

2、实现方法:

1)input框输入金额,并添加聚焦,离开事件

页面上添加内容:

<inputv-model="displayValue"@input="handleInput"@blur="handleBlur"@focus="handleFocus"placeholder="请输入金额"
/>

js中增加配置

const displayValue = ref('')
const rawValue = ref(0)const handleInput = (e) => {let val = e.detail.value
}// 处理失去焦点
const handleBlur = () => {
}// 处理获取焦点
const handleFocus = () => {
}

2)输入的内容,处理非数字内容,还有只能有一个小数点,小数点后添加2位限制,最大值限制

const displayValue = ref('') //千分位处理后的字段
const rawValue = ref(0)      //拿到的实际内容数据
const maxFloatNum = ref(2)  //限制小数点后几位
const maxNum = ref(100000000000) //设置最大值
const handleInput = (e) => {let val = e.detail.valueif(!val) return ''let value = val.toString().replace(/[^\d.]/g, '')if (value.length > 1 && value.startsWith('0')) {value = value.substring(1)}const min = 0const max = maxNum.value// 确保只有一个点const parts = value.split('.')if (parts.length > 2) {value = parts[0] + '.' + parts.slice(1).join('')}// 限制小数点后两位if (parts.length === maxFloatNum.value) {value = parts[0] + '.' + parts[1].slice(0, maxFloatNum.value)}// 转换为数字const numValue = parseFloat(value || 0)// 检查范围if (numValue > max) {value = max.toString()} else if (numValue < min) {value = min.toString()}rawValue.value = numValuedisplayValue.value = value}

3)聚焦和离开时候将数据转换位千分位,通过正则

// 格式化显示值(添加千分位)const formatDisplay = (value) => {const num = parseFloat(value || 0)return num.toFixed(maxFloatNum.value).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
// 处理失去焦点
const handleBlur = () => {displayValue.value = formatDisplay(rawValue.value)
}// 处理获取焦点
const handleFocus = () => {displayValue.value = rawValue.value.toString()
}

4)来写一个大小写转换的功能,并展示到界面input上面,配合样式

js中封装小写转大写方法
//封装的小写转大写方法,适合各种场景const amountToChinese = (num)=> {const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']const cnIntRadice = ['', '拾', '佰', '仟']const cnIntUnits = ['', '万', '亿', '兆']const cnDecUnits = ['角', '分', '毫', '厘']const cnInteger = '整'const cnIntLast = '元'if(num > maxNum.value){return '-'}// 处理负数let sign = '';if (num < 0) {sign = '负';num = Math.abs(num);}// 分离整数和小数部分let numStr = num.toString();let integerStr = '';let decimalStr = '';if (numStr.indexOf('.') !== -1) {const parts = numStr.split('.');integerStr = parts[0];decimalStr = parts[1].substring(0, 4); // 最多支持4位小数} else {integerStr = numStr;}// 处理整数部分let chineseInteger = '';if (parseInt(integerStr, 10) > 0) {let zeroCount = 0;const intLen = integerStr.length;for (let i = 0; i < intLen; i++) {const n = integerStr.charAt(i);const p = intLen - i - 1;const q = p / 4;const m = p % 4;if (n === '0') {zeroCount++;} else {if (zeroCount > 0) {chineseInteger += cnNums[0];}zeroCount = 0;chineseInteger += cnNums[parseInt(n)] + cnIntRadice[m];}if (m === 0 && zeroCount < 4) {chineseInteger += cnIntUnits[q];}}chineseInteger += cnIntLast;}// 处理小数部分let chineseDecimal = '';if (decimalStr) {for (let i = 0; i < decimalStr.length; i++) {const n = decimalStr.charAt(i);if (n !== '0') {chineseDecimal += cnNums[parseInt(n)] + cnDecUnits[i];}}}// 组合结果let result = sign + chineseInteger + chineseDecimal;if (!chineseInteger && !chineseDecimal) {result = cnNums[0] + cnIntLast + cnInteger;} else if (!chineseDecimal) {result += cnInteger;}return result;}
样式中通过定位,来实现input上面内容的展示
<style lang="scss" scoped>.moneyInputBox{position: relative;input{width: 100%;padding: 0 10rpx !important;box-sizing: border-box !important;border: 1rpx solid #dadbde;height: 62rpx !important;line-height: 42rpx!important;border-radius: 4px;}.bigNumBox{position: absolute;bottom: 76rpx;width:auto;background: rgba(0,0,0,.5);padding:10rpx;color:#fff;border-radius: 20rpx;border:1rpx solid #dadbde;}}
</style>

5)将我们当前的组件,用watch监听+emit发送的方法,实现数据的双向绑定,可以在父级用v-model来绑定内容

js具体配置:
<script setup>import { ref, watch, defineProps, defineEmits } from 'vue'const props = defineProps({modelValue: {type: [Number, String],default: 0}})const emit = defineEmits(['update:modelValue'])// 监听外部传入的modelValue变化watch(() => props.modelValue, (newVal) => {if (newVal !== rawValue.value) {rawValue.value = parseFloat(newVal) || 0displayValue.value = formatDisplay(rawValue.value)bigNumCont.value = amountToChinese(rawValue.value)}}, { immediate: true })  </script>
父级调用:
<moneyInput v-model="moneyNum"></moneyInput><script setup>const moneyNum = ref(100)

封装代码源码  moneyInput.vue

<template><view class="moneyInputBox"><inputv-model="displayValue"@input="handleInput"@blur="handleBlur"@focus="handleFocus"placeholder="请输入金额"/><view v-if="showBigNum" class="bigNumBox">{{bigNumCont}}</view></view>
</template><script setup>import { ref, watch, defineProps, defineEmits } from 'vue'const props = defineProps({modelValue: {type: [Number, String],default: 0}})const emit = defineEmits(['update:modelValue'])const displayValue = ref('')const rawValue = ref(0)const maxFloatNum = ref(2)const maxNum = ref(100000000000)const showBigNum = ref(false)const bigNumCont = ref('')// 格式化显示值(添加千分位)const formatDisplay = (value) => {const num = parseFloat(value || 0)return num.toFixed(maxFloatNum.value).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}// 处理输入变化const handleInput = (e) => {let val = e.detail.valueif(!val) return ''let value = val.toString().replace(/[^\d.]/g, '')if (value.length > 1 && value.startsWith('0')) {value = value.substring(1)}const min = 0const max = maxNum.value// 确保只有一个点const parts = value.split('.')if (parts.length > 2) {value = parts[0] + '.' + parts.slice(1).join('')}// 限制小数点后两位if (parts.length === maxFloatNum.value) {value = parts[0] + '.' + parts[1].slice(0, maxFloatNum.value)}// 转换为数字const numValue = parseFloat(value || 0)// 检查范围if (numValue > max) {value = max.toString()} else if (numValue < min) {value = min.toString()}rawValue.value = numValuedisplayValue.value = valuebigNumCont.value = amountToChinese(rawValue.value)emit('update:modelValue', rawValue.value)}// 处理失去焦点const handleBlur = () => {showBigNum.value = falsedisplayValue.value = formatDisplay(rawValue.value)bigNumCont.value = amountToChinese(rawValue.value)}// 处理获取焦点const handleFocus = () => {showBigNum.value = truedisplayValue.value = rawValue.value.toString()bigNumCont.value = amountToChinese(rawValue.value)}const amountToChinese = (num)=> {const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']const cnIntRadice = ['', '拾', '佰', '仟']const cnIntUnits = ['', '万', '亿', '兆']const cnDecUnits = ['角', '分', '毫', '厘']const cnInteger = '整'const cnIntLast = '元'if(num > maxNum.value){return '-'}// 处理负数let sign = '';if (num < 0) {sign = '负';num = Math.abs(num);}// 分离整数和小数部分let numStr = num.toString();let integerStr = '';let decimalStr = '';if (numStr.indexOf('.') !== -1) {const parts = numStr.split('.');integerStr = parts[0];decimalStr = parts[1].substring(0, 4); // 最多支持4位小数} else {integerStr = numStr;}// 处理整数部分let chineseInteger = '';if (parseInt(integerStr, 10) > 0) {let zeroCount = 0;const intLen = integerStr.length;for (let i = 0; i < intLen; i++) {const n = integerStr.charAt(i);const p = intLen - i - 1;const q = p / 4;const m = p % 4;if (n === '0') {zeroCount++;} else {if (zeroCount > 0) {chineseInteger += cnNums[0];}zeroCount = 0;chineseInteger += cnNums[parseInt(n)] + cnIntRadice[m];}if (m === 0 && zeroCount < 4) {chineseInteger += cnIntUnits[q];}}chineseInteger += cnIntLast;}// 处理小数部分let chineseDecimal = '';if (decimalStr) {for (let i = 0; i < decimalStr.length; i++) {const n = decimalStr.charAt(i);if (n !== '0') {chineseDecimal += cnNums[parseInt(n)] + cnDecUnits[i];}}}// 组合结果let result = sign + chineseInteger + chineseDecimal;if (!chineseInteger && !chineseDecimal) {result = cnNums[0] + cnIntLast + cnInteger;} else if (!chineseDecimal) {result += cnInteger;}return result;}// 监听外部传入的modelValue变化watch(() => props.modelValue, (newVal) => {if (newVal !== rawValue.value) {rawValue.value = parseFloat(newVal) || 0displayValue.value = formatDisplay(rawValue.value)bigNumCont.value = amountToChinese(rawValue.value)}}, { immediate: true })
</script><style lang="scss" scoped>.moneyInputBox{position: relative;input{width: 100%;padding: 0 10rpx !important;box-sizing: border-box !important;border: 1rpx solid #dadbde;height: 62rpx !important;line-height: 42rpx!important;border-radius: 4px;}.bigNumBox{position: absolute;bottom: 76rpx;width:auto;background: rgba(0,0,0,.5);padding:10rpx;color:#fff;border-radius: 20rpx;border:1rpx solid #dadbde;}}
</style>

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

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

相关文章

途游Android面试题及参考答案

对 Java 面向对象的理解是什么?多态的实现方法有哪些? Java 面向对象是一种编程思想,核心在于将现实世界中的事物抽象为 “对象”,每个对象由 “属性”(数据)和 “方法”(行为)组成,通过对象之间的交互完成功能。其核心特性包括封装、继承和多态: 封装是指将对象的属…

通过filezilla在局域网下实现高速传输数据

一. filezilla安装 1.1 linux安装 sudo apt update sudo apt install openssh-server1.2 windows安装 windows安装可以参考这篇文章 二. 使用方法 2.1 wifi下使用方法 直接查看想要连接的电脑的ip&#xff0c;其他的按照有线网络设置好了ip之后进行连接就行。 2.2 有线网…

python的易物小店交换系统

前端开发框架:vue.js 数据库 mysql 版本不限 后端语言框架支持&#xff1a; 1 java(SSM/springboot)-idea/eclipse 2.NodejsVue.js -vscode 3.python(flask/django)–pycharm/vscode 4.php(thinkphp/laravel)-hbuilderx 数据库工具&#xff1a;Navicat/SQLyog等都可以 在需求分…

[硬件电路-119]:模拟电路 - 信号处理电路 - 比较器,模拟电路中的“决策者”,模拟信号到数字电平逻辑信号的转化者...

前言&#xff1a;比较器的价值1、为何称比较器为“决策者”&#xff1f;逻辑判断的物理实现比较器通过硬件电路直接完成“大于/小于”的二元判断&#xff0c;无需软件干预。例如&#xff1a;在过压保护电路中&#xff0c;比较器实时监测输入电压 Vin​ 与参考电压 Vref​&#…

【从零开始学习Redis】初识Redis

初识Redis 一句话理解Redis&#xff1a; Redis是一个基于内存的、支持多种数据结构的高性能键值数据库&#xff0c;常被用于缓存、分布式锁和消息队列。和 MySQL 的区别&#xff1a;特点RedisMySQL类型非关系型&#xff08;NoSQL&#xff09;关系型&#xff08;SQL&#xff09;…

CUDA杂记--nvcc使用介绍

nvcc 是 NVIDIA CUDA 生态的核心编译器&#xff0c;负责将 CUDA C/C 代码&#xff08;混合了主机代码和设备代码&#xff09;编译为可在 CPU 和 GPU 上运行的二进制文件。它不仅是一个简单的编译器&#xff0c;更是一个“编译驱动程序”&#xff0c;协调多个工具链&#xff08;…

Codeforces Round 1040 (Div. 2)(补题)

文章目录前言A.Submission is All You NeedB. PathlessC.Double PerspectiveD.Stay or Mirror前言 又被卡在第二题了&#xff0c;当时脑子跟犯糊涂似的&#xff0c;B题越理越乱&#xff0c;导致比赛结束&#xff0c;还在想着题&#xff0c;彻夜难眠&#xff01; A.Submission …

Apifox 7 月更新|通过 AI 命名参数及检测接口规范、在线文档支持自定义 CSS 和 JavaScript、鉴权能力升级

Apifox 新版本上线啦&#xff01; 看看本次版本更新主要涵盖的重点内容&#xff0c;有没有你所关注的功能特性&#xff1a; AI 助力接口设计 通过 AI 为参数命名 支持让 AI 对接口进行规范性检测 在线文档功能增强 在线文档支持自定义 CSS 和 JavaScript 目录支持设置展示…

Node.js以及异步编程

什么是服务器&#xff1f;我们知道客户端通过访问服务器&#xff0c;然后服务器去操作数据库把我们想要的数据拿过来给客户端。比如服务器就是餐厅的服务员&#xff0c;数据库就是厨房&#xff0c;客户端就是我们的顾客。首先我们点菜&#xff0c;服务器告诉厨师做饭&#xff0…

UniApp 实现顶部固定导航栏 Tab 及滚动变色效果

顶部导航栏是一个非常常见的组件&#xff0c;尤其是固定在顶部的 Tab 导航&#xff0c;既能方便用户快速切换内容&#xff0c;又能保持页面结构的清晰。本文将详细介绍如何在 UniApp Vue3 TypeScript 项目中实现一个固定在顶部、且能根据滚动状态改变样式的 Tab 导航栏。效果…

c++泛型编程

C泛型编程 1. 基本概念 1.1 泛型编程&#xff08;Generic Programming&#xff09; 泛型编程是C中一种重要的编程范式&#xff0c;它通过 参数化类型 来实现代码的通用性和复用性。 1.2 模板&#xff08;Templates&#xff09; 模板 是泛型编程的基础&#xff0c;允许编写与数据…

Vue.js + Node.js 开发前后台框架

在 Vue.js + Node.js 开发前后台框架时,推荐采用现代化的技术栈组合和最佳实践。以下是一个高效、可扩展的全栈框架方案: 技术栈推荐 层级 技术选型 说明 前端框架 Vue 3 (Composition API) 最新Vue核心库,推荐使用<script setup>语法 UI组件库 Element Plus / Ant D…

Vision Transformer (ViT) 详解:当Transformer“看见”世界,计算机视觉的范式革命

摘要: 长久以来&#xff0c;卷积神经网络&#xff08;CNN&#xff09;凭借其精心设计的归纳偏置&#xff08;inductive biases&#xff09;&#xff0c;无可争议地统治着计算机视觉领域。然而&#xff0c;一篇名为《An Image is Worth 16x16 Words》的论文彻底改变了这一格局&a…

go goroutine chan 用法

方法1 代码 package mainimport ("fmt""sync""time" )func main() {allChan : make(chan interface{}, 3)var sendWg, recvWg sync.WaitGroup // 分别同步发送和接收// 发送goroutinesendWg.Add(1)go func() {defer sendWg.Done()for i : 0; i &…

Web前端文件上传安全与敏感数据安全处理

一、文件上传安全1. 文件上传时的核心安全检查点文件上传是 Web 应用的高风险功能&#xff0c;需从多维度验证&#xff0c;防止恶意文件上传&#xff08;如木马、病毒&#xff09;或路径攻击&#xff0c;关键检查点包括&#xff1a;MIME 类型验证检查请求头中的 Content-Type&a…

文法中的间接左递归

&#x1f31f; 第一步&#xff1a;理解基本概念✅ 什么是文法&#xff08;Grammar&#xff09;&#xff1f;在编程语言或语法分析中&#xff0c;文法 是一组规则&#xff0c;用来描述一种语言的结构。例如&#xff1a;S → A a A → B b B → S c 这表示&#xff1a;S 可以…

Anthropic:跨越生产效能拐点的AI增长飞轮

资本竞赛中的战略转折点 人工智能领域的竞争已经从理念之争演变为资本、算力与地缘政治影响力的全面较量。Anthropic传闻中的1700亿美元估值&#xff0c;如果成为现实&#xff0c;将标志着前沿AI发展格局的地震式转变。这不仅仅是构建更智能模型的问题&#xff0c;更是为主导下…

【Unity3D实例-功能-移动】小兵移动-通过鼠标点击进行

在Unity的世界里&#xff0c;当你轻点鼠标&#xff0c;角色仿佛被赋予了新的使命&#xff0c;沿着一条无形的轨迹&#xff0c;向着地图上的目标点进发。每一次移动&#xff0c;不仅是简单的位移&#xff0c;更是对未知的探索。这种交互&#xff0c;让玩家与游戏世界紧密相连&am…

从0到1学PHP(十四):PHP 性能优化:打造高效应用

目录一、PHP 性能评估与分析1.1 性能指标体系1.2 性能分析工具使用1.3 性能瓶颈定位方法与流程二、代码层面优化技巧2.1 高效的循环与条件判断写法2.2 函数与类的优化设计2.3 内存管理与垃圾回收机制优化三、缓存策略与实现3.1 数据缓存3.2 页面缓存与部分缓存技术3.3 OPcache …

移动管家手机控车系统硬件安装与软件绑定设置

移动管家手机控车系统硬件安装与软件绑定配合使用&#xff0c;具体设置步骤如下&#xff1a;一、硬件安装准备 ‌加装智能控制主机‌&#xff1a;需在车辆上加装移动管家专用智能控制模块&#xff0c;该模块需与原车电路系统连接&#xff0c;并将原车钥匙芯片焊接至主控盒内以实…