首页
关于叶子
Search
1
Win10突然出现不能连接共享打印机一例
359,593 阅读
2
[经验存档] 微星(MSI)B150M-Pro-VD Plus安装系统蓝屏一例
205,309 阅读
3
Laravel“高并发”导致数据“统计”异常一例
98,231 阅读
4
Laravel 9高并发API数据操作的最佳实践
62,437 阅读
5
[iOS|Xcode]iOS-App自定义启动页制作(uniapp适用)
55,934 阅读
代码
分享
琐事
MySQL
数码
前端
MacOS
软件
Windows
PHP
GoLang学习
登录
Search
标签搜索
Laravel
PHP
Windows
Laravel-Admin
Vue
uniapp
前端
CSS
chartjs
HTML
微信
小程序
web
MacOS
App
iOS
工具
Golang
微服务
高并发
Yesr00
累计撰写
65
篇文章
累计收到
8
条评论
首页
栏目
代码
分享
琐事
MySQL
数码
前端
MacOS
软件
Windows
PHP
GoLang学习
页面
关于叶子
搜索到
7
篇与
的结果
2026-03-09
Vue 实战:如何完美控制 El-Input 数值输入(范围、步长与自动修正)
在开发后台管理系统或评分组件时,我们经常遇到这样的需求:用户需要输入一个数值,该数值必须在特定范围内(例如 0 到 5),且必须是固定步长的倍数(例如 0.5)。看似简单的需求,在实际使用 Element Plus (或 Element UI) 的 el-input 组件时,却常常踩坑。浏览器原生的 min、max 和 step 属性往往“防君子不防小人”,用户依然可以通过手动输入非法值。本文将复盘一个真实的开发场景,从问题现象出发,提供一套稳健的解决方案。痛点:原生属性的局限性假设我们需要一个评分框,要求如下:范围:大于 0,小于等于 5。步长:必须是 0.5 的倍数(如 0.5, 1.0, 1.5...)。格式:保留一位小数。初版代码通常长这样:问题出现了:虽然设置了 min、max 和 step,但用户依然可以在输入框中手动敲入 6、8.8 甚至 100。原因:HTML5 的 type="number" 配合 min/max 通常只在表单提交或失去焦点时才进行验证,而不会在输入过程中实时拦截。体验:用户输入了非法值,界面没有即时反馈,直到提交报错,体验极差。此外,step 属性在手动输入时,默认行为往往是“向下取整”而非我们期望的“四舍五入”。核心思路:数据驱动修正要解决这些问题,不能依赖浏览器的原生行为,必须将控制权收回到 Vue 的数据流中。我们需要在用户输入的每一个瞬间(@input 事件),对数据进行“清洗”和“修正”。我们的处理逻辑应该包含三个步骤:解析:将输入字符串转为数字。限幅:强制将数值限制在 [0, 5] 区间内。对齐:将数值四舍五入到最近的 0.5 倍数。解决方案:自定义 Input 处理器下面是一个经过生产环境验证的完整实现方案。我们将逻辑封装在 handleInput 方法中,既保证了数据的合法性,又提供了流畅的用户体验。代码实现请输入评分 (0.5 - 5.0): 当前有效值:{{ actualScore }} import { ref, watch } from 'vue';// 实际存储的有效数值const actualScore = ref(0);// 绑定在输入框上的显示值(字符串格式,用于控制小数位)const displayValue = ref('0');/** 核心处理逻辑 规则: 必须大于 0 且小于等于 5 必须是 0.5 的倍数 自动四舍五入到最近的 0.5 */const handleInput = (val) => { // 1. 处理空值或非数字情况 if (!val && val !== 0) {displayValue.value = ''; actualScore.value = 0; return;}const num = parseFloat(val);// 如果解析失败,保持原状或清空(视业务需求而定) if (isNaN(num)) {return; }// 2. 限幅处理 (Clamping) // 小于 0 变为 0,大于 5 变为 5 let clamped = Math.max(0, Math.min(5, num));// 3. 步长对齐 (Stepping) // 技巧:乘以 2 -> 四舍五入 -> 除以 2 // 例如:1.2 * 2 = 2.4 -> round(2.4) = 2 -> 2 / 2 = 1.0 // 例如:1.3 * 2 = 2.6 -> round(2.6) = 3 -> 3 / 2 = 1.5 let rounded = Math.round(clamped * 2) / 2;// 4. 更新数据 actualScore.value = rounded;// 5. 格式化显示:强制保留一位小数 // 注意:这里直接修改 displayValue 会再次触发 input 事件吗? // 在 Vue 中,如果是 v-model 绑定的变量在 handler 中被修改, // 需要注意避免死循环。但在本例中,toFixed 产生的新字符串 // 如果与当前输入一致则不会触发,若不一致(如用户输 1.2 变 1.0) // 会触发一次,但逻辑是幂等的,所以是安全的。 displayValue.value = rounded.toFixed(1);};// 初始化handleInput(0);.score-container { padding: 20px; font-family: sans-serif;}.tip { margin-top: 10px; color: #666; font-size: 14px;}关键技术点解析为什么不用 step 属性做主要约束?step 属性在使用上下箭头按钮时非常有用,但在键盘直接输入时,它几乎不起作用。而且原生的步进逻辑通常是截断(Truncate),不符合“四舍五入”的直觉。通过数学计算 Math.round(num * 2) / 2,我们可以精确控制 rounding 行为。浮点数精度陷阱在判断是否为 0.5 倍数时,不要直接使用 num % 0.5 === 0。由于 JavaScript 浮点数精度问题(如 0.1 + 0.2),直接取余可能会得到极其接近 0 但不等于 0 的值。最佳实践是使用“乘法转整数法”:// 错误示范if (num % 0.5 !== 0) { ... }// 正确示范const isHalfStep = Math.abs((num 2) - Math.round(num 2)) 5) return false;// 步长检查:是否为 0.5 的倍数 // 乘以 2 后应为整数 const doubled = num * 2; return Math.abs(doubled - Math.round(doubled)) < Number.EPSILON;}总结在处理数值输入时,永远不要信任浏览器的原生验证行为。实时拦截:利用 @input 事件在数据进入模型前进行清洗。数学修正:使用 Math.max/min 限制范围,使用 Math.round(x * n) / n 处理步长对齐。格式化展示:利用 toFixed 确保用户体验的一致性。这套模式不仅适用于评分组件,也适用于任何需要特定精度和范围控制的金融、统计类输入场景。
2026年03月09日
14 阅读
0 评论
0 点赞
2025-04-09
使用Element-UI Table组件动态增减行/列导致表格错位的问题
整体异常大致如下图所示:需求场景:除了第一列表头是固定写死的,每一行和每一列的数据都是来自接口数据,基于当前项目使用的Element-UI,于是用组件实现。解决:基于这是一个必现的问题,结合文档以及群里大佬的提示,最后使用this.$refs.table?.doLayout()用以刷新表格布局,故障解决。仅作记录用,欢迎巨佬们交流
2025年04月09日
24,980 阅读
0 评论
0 点赞
2022-11-05
【前端|JavaScript】一种比较"偏门"的数据格式处理
最近在写前端的时候碰到一种比较"偏门"的数据格式,大致如下: [pre lang="JSON"] data: { civil: { 0: '3000-4500', }, criminal: { 0: '1500', 1: '2000', 2: '3000', }, administrative: { 0: '2500-3750', }, charge: { 0: { '0-2': '800', }, 1: { '2-10': '4', }, 2: { '10-50': '3', }, 3: { '50-100': '2', }, 4: { '100-500': '1', }, 5: { '500-1000': '0.5', }, 6: { '1000-5000': '0.2', }, 7: { '5000-Infinity': '这是最终的处理方式', }, }, },[/pre]算是一个多维的数组对象?需求大概是这样子的,根据条件分别取到对应层级下的某个key范围内的值,也就是比如我当前条件是要求取charge下的2-10之间的对应值,直接用下标取肯定是不合适的,这个时候呢,就只能用如下的方法去取,(仅记录,可能有更优的方法?欢迎交流)设定已经把上面格式赋值给了data变量,那么就会有如下代码: [pre lang="javascript"] let charge = data.charge; Object.values(charge).map((item)=>{ //>Object.keys取下标,也就是取(2-10,10-50)这个下标 console.log(Object.keys(item)); //>Object.values取值,通过条件对比是否在下标范围内,在下标范围内则进行赋值或者对应操作. console.log(Object.values(item)) }) [/pre]以上,记录下来防止以后再碰上忘记.欢迎各位大佬指教.
2022年11月05日
1,447 阅读
0 评论
0 点赞
2022-06-29
【VSCode】ES-LINT提示插件提示屏蔽(非语法错误)
最近在用VSCode写代码的时候发现,ES-LINT会有一些莫名的提示,比如,我注释习惯用 //> 这样子的开头。。。但是在ES-LINT的默认提示里就会说必须在注释里强行加空格,也就是要 // >这样,才不会出错。。。又比如 我写一个switch, 根据习惯来说,case是不会和switch持平的。。。但是es-lint默认要求他们持平才不报错。。。综上所述,虽然编译过程中并不报错,但是编辑器里的这种提示很是扎眼。。。一通搜索之后,在.eslintrc的rules里增加如下规则: //>注释后不加空格 "spaced-comment": [ 0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] } ], //>switch对齐 "indent": [ 2, 2, { "SwitchCase": 1 } ],
2022年06月29日
2,945 阅读
0 评论
0 点赞
2022-04-23
【Vue】canvas画图之小程序“隐藏”画布
近期在工作上有项目使用到canvas来生成图片,并提供下载的功能。基于canvas不支持自适应,都是用的px作为单位。当然网络上也有一些教程是使用比如计算像素比来金星等比例调整的。我也参考了网络上的几种方式进行了一些调整操作。发现都是有些不太稳妥,最后还是采取了生成图片后隐藏画布,用img来展示图片并提供下载(保存)的功能。也的确是可以实现的,但是,在这个过程中会有一个canvas隐藏然后展示img的切换过程,画面一闪而过的。。。在用户使用体验上并不是太好,但是又不能在一开始就把canvas给隐藏掉。否则draw()的回调进不去。于是在思考再三,尝试如下操作: <view style="top:-999999999999rpx;"> <canvas canvas-id="canvasId" id="canvasId"></canvas> </view> 这个操作把画布移除了当前的展示区与。然后在画图过程中使用loading加载框,在会话完成后隐藏loading加载框,展示图片。体验上就好了许多,又不会导致画图出现问题。顺便记录一下,canvas画布 宽高使用100%,不给宽高,都有可能导致draw回调不执行,小程序下添加type="2d" 标签也可能导致画布不显示。
2022年04月23日
5,913 阅读
0 评论
0 点赞
1
2