news 2026/4/15 3:32:29

Vue3 + TypeScript + el-input 处理年份输入(最多只能输入四位数字,不能输入其他符号)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3 + TypeScript + el-input 处理年份输入(最多只能输入四位数字,不能输入其他符号)

代码:

// 处理年份输入,最多只能输入四位数字,不能输入其他符号 const handleYearInput = (value: string) => { // 过滤掉所有非数字字符,只保留数字 const numbersOnly = value.replace(/[^\d]/g, ""); // 限制4位 const limitedValue = numbersOnly.slice(0, 4); // 转换为数字,空字符串设为0 localCapitalInfo.capitalYear = limitedValue === "" ? 0 : parseInt(limitedValue, 10); }; <el-input v-model="localCapitalInfo.capitalYear" clearable @input="handleYearInput" />

效果:


Vue3年份输入控制最佳实践

vue3中, // 处理年份输入,最多只能输入四位数字,不能输入其他符号 const handleYearInput = (value: string) => { // 过滤掉所有非数字字符,只保留数字 const numbersOnly = value.replace(/[^\d]/g, ""); // 限制4位 const limitedValue = numbersOnly.slice(0, 4); // 转换为数字,空字符串设为0 localCapitalInfo.capitalYear = limitedValue === "" ? 0 : parseInt(limitedValue, 10); }; ...... <el-row :gutter="10"> <el-col :span="12"> <el-form-item label="资金序号" label-position="right" prop="capitalNo"> <el-input v-model="localCapitalInfo.capitalNo" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="资金年份" label-position="right" prop="capitalYear"> <el-input v-model="localCapitalInfo.capitalYear" clearable @input="handleYearInput" /> </el-form-item> </el-col> </el-row> ...... <el-row :gutter="10"> <el-col :span="24"> <el-form-item label="资金年份" label-position="right"> <el-input v-model="capitalInfoStore.queryDTO.capitalYear" clearable /> </el-form-item> </el-col> </el-row> 如何更好地实现这两处资金年份的输入控制

在 Vue3 中,可以通过以下几种方式更好地实现年份输入控制:

方案一:使用计算属性 + 自定义指令(推荐)

1. 创建自定义指令

typescript

// directives/inputDirectives.ts import { Directive } from 'vue' // 只能输入数字的自定义指令 export const numberDirective: Directive = { mounted(el) { el.addEventListener('input', (e: Event) => { const input = e.target as HTMLInputElement input.value = input.value.replace(/[^\d]/g, '') }) } } // 限制最大长度的自定义指令 export const maxLengthDirective: Directive = { mounted(el, binding) { const maxLength = binding.value || 4 el.addEventListener('input', (e: Event) => { const input = e.target as HTMLInputElement if (input.value.length > maxLength) { input.value = input.value.slice(0, maxLength) } }) } }

2. 在组件中使用

vue

<template> <el-row :gutter="10"> <el-col :span="12"> <el-form-item label="资金年份" label-position="right" prop="capitalYear"> <el-input v-model.number="localCapitalInfo.capitalYear" :maxlength="4" clearable v-number v-max-length="4" @blur="validateYear" /> </el-form-item> </el-col> </el-row> </template> <script setup lang="ts"> import { ref, computed } from 'vue' import { numberDirective, maxLengthDirective } from '@/directives/inputDirectives' const vNumber = numberDirective const vMaxLength = maxLengthDirective // 使用计算属性处理年份 const localCapitalInfo = ref({ capitalYear: 0 }) // 年份计算属性 const yearValue = computed({ get() { return localCapitalInfo.value.capitalYear || '' }, set(value) { if (value === '') { localCapitalInfo.value.capitalYear = 0 } else { const num = parseInt(value, 10) if (!isNaN(num) && num >= 0) { localCapitalInfo.value.capitalYear = Math.min(num, 9999) } } } }) // 验证年份 const validateYear = () => { const year = localCapitalInfo.value.capitalYear if (year < 1900 || year > 2100) { // 可以添加错误提示 console.warn('请输入有效的年份(1900-2100)') } } </script>

方案二:创建可复用的 Composable

1. 创建 useYearInput Composable

typescript

// composables/useYearInput.ts import { ref, computed, watch } from 'vue' export function useYearInput(initialValue = 0, options = { min: 1900, max: 2100, maxLength: 4 }) { const rawValue = ref<string>(initialValue?.toString() || '') const error = ref<string>('') // 处理输入 const handleInput = (value: string) => { // 只保留数字 const numbersOnly = value.replace(/[^\d]/g, '') // 限制长度 rawValue.value = numbersOnly.slice(0, options.maxLength) // 验证 validate() } // 验证年份 const validate = () => { if (rawValue.value === '') { error.value = '' return true } const yearNum = parseInt(rawValue.value, 10) if (isNaN(yearNum)) { error.value = '请输入有效的年份' return false } if (yearNum < options.min || yearNum > options.max) { error.value = `年份范围:${options.min}-${options.max}` return false } error.value = '' return true } // 获取数字值 const yearNumber = computed(() => { if (rawValue.value === '') return 0 const num = parseInt(rawValue.value, 10) return isNaN(num) ? 0 : num }) // 获取显示值 const displayValue = computed({ get: () => rawValue.value, set: (value: string) => handleInput(value) }) return { rawValue, displayValue, yearNumber, error, handleInput, validate } }

2. 在组件中使用

vue

<template> <el-row :gutter="10"> <el-col :span="12"> <el-form-item label="资金年份" label-position="right" prop="capitalYear" :error="yearInput.error" > <el-input v-model="yearInput.displayValue" :maxlength="4" clearable placeholder="请输入年份" @blur="yearInput.validate" /> </el-form-item> </el-col> </el-row> </template> <script setup lang="ts"> import { useYearInput } from '@/composables/useYearInput' import { watch } from 'vue' const yearInput = useYearInput(2023, { min: 1900, max: 2100, maxLength: 4 }) // 如果需要,可以监听数值变化 watch(() => yearInput.yearNumber, (newVal) => { // 更新到 store 或父组件 }) </script>

方案三:创建 YearInput 组件(最推荐)

1. 创建 YearInput 组件

vue

<!-- components/YearInput.vue --> <template> <el-input :model-value="displayValue" :maxlength="4" :placeholder="placeholder" :clearable="clearable" :disabled="disabled" :error="!!errorMessage" @input="handleInput" @blur="handleBlur" > <template #append v-if="showSuffix">年</template> </el-input> <div v-if="errorMessage" class="error-message"> {{ errorMessage }} </div> </template> <script setup lang="ts"> import { ref, computed, watch } from 'vue' interface Props { modelValue?: number | string placeholder?: string clearable?: boolean disabled?: boolean showSuffix?: boolean minYear?: number maxYear?: number required?: boolean } const props = withDefaults(defineProps<Props>(), { modelValue: 0, placeholder: '请输入年份', clearable: true, disabled: false, showSuffix: true, minYear: 1900, maxYear: 2100, required: false }) const emit = defineEmits<{ 'update:modelValue': [value: number] 'change': [value: number] 'validate': [isValid: boolean] }>() const rawValue = ref<string>('') const errorMessage = ref<string>('') // 初始化 watch(() => props.modelValue, (value) => { if (value || value === 0) { rawValue.value = value.toString() } }, { immediate: true }) // 显示值 const displayValue = computed(() => rawValue.value) // 处理输入 const handleInput = (value: string) => { // 只保留数字 const numbersOnly = value.replace(/[^\d]/g, '') // 限制长度 rawValue.value = numbersOnly.slice(0, 4) // 实时更新 updateValue() } // 更新值 const updateValue = () => { if (rawValue.value === '') { emit('update:modelValue', 0) emit('change', 0) return } const yearNum = parseInt(rawValue.value, 10) if (!isNaN(yearNum)) { const finalValue = Math.min(Math.max(yearNum, 0), 9999) emit('update:modelValue', finalValue) emit('change', finalValue) } } // 验证 const handleBlur = () => { validate() } const validate = (): boolean => { errorMessage.value = '' if (props.required && !rawValue.value) { errorMessage.value = '年份不能为空' emit('validate', false) return false } if (!rawValue.value) { emit('validate', true) return true } const yearNum = parseInt(rawValue.value, 10) if (isNaN(yearNum)) { errorMessage.value = '请输入有效的年份' emit('validate', false) return false } if (yearNum < props.minYear || yearNum > props.maxYear) { errorMessage.value = `年份范围:${props.minYear}-${props.maxYear}` emit('validate', false) return false } emit('validate', true) return true } // 暴露方法 defineExpose({ validate, clear: () => { rawValue.value = '' updateValue() } }) </script> <style scoped> .error-message { color: #f56c6c; font-size: 12px; margin-top: 4px; } </style>

2. 在父组件中使用

vue

<template> <el-row :gutter="10"> <el-col :span="12"> <el-form-item label="资金年份" label-position="right" prop="capitalYear"> <YearInput v-model="localCapitalInfo.capitalYear" :min-year="2000" :max-year="2100" required /> </el-form-item> </el-col> </el-row> <el-row :gutter="10"> <el-col :span="24"> <el-form-item label="资金年份" label-position="right"> <YearInput v-model="capitalInfoStore.queryDTO.capitalYear" :clearable="true" /> </el-form-item> </el-col> </el-row> </template> <script setup lang="ts"> import YearInput from '@/components/YearInput.vue' import { ref } from 'vue' const localCapitalInfo = ref({ capitalYear: 2023 }) // 使用 store import { useCapitalInfoStore } from '@/stores/capitalInfo' const capitalInfoStore = useCapitalInfoStore() </script>

方案四:使用第三方库(如 v-mask)

bash

npm install vue-the-mask

vue

<template> <el-input v-model="yearValue" v-mask="'####'" placeholder="YYYY" clearable /> </template> <script setup lang="ts"> import { ref, watch } from 'vue' import { VueMaskDirective } from 'vue-the-mask' const vMask = VueMaskDirective const yearValue = ref('') </script>

总结建议

  1. 推荐方案三:创建YearInput组件,封装性好,可复用性强

  2. 次推荐方案二:使用 Composable,逻辑复用方便

  3. 简单场景:可以使用计算属性 + 自定义指令

  4. 优势

    • 统一处理逻辑,避免重复代码

    • 支持验证和错误提示

    • 易于维护和扩展

    • 类型安全(TypeScript)

根据项目复杂度和复用需求选择合适的方案,组件化方式更适合长期维护的项目。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 21:07:14

BAT 精准提权脚本(直接提权优先 + UAC 兜底 + 全程校验无静默失败)

为你编写优先直接提权、失败弹 UAC 确认、全链路校验无静默异常的 BAT 脚本&#xff0c;彻底解决「提权检测误判、无报错无反馈、实际未提权却执行后续操作」的核心问题。脚本核心逻辑&#xff1a;先严格检测是否为管理员权限→是则直接执行业务→否则生成安全的 VBS 触发 UAC …

作者头像 李华
网站建设 2026/4/13 18:35:44

虚拟人:从数字分身到元宇宙公民的技术演进与未来展望

引言&#xff1a;什么是虚拟人&#xff1f;虚拟人&#xff08;Digital Human/Meta Human&#xff09;是通过数字技术构建的、具有数字化外形的虚拟人物&#xff0c;它们拥有类人外观、行为特征及交互能力。这些虚拟存在不仅具备人类的相貌、性别和性格特征&#xff0c;还能用语…

作者头像 李华
网站建设 2026/4/3 22:33:39

工业AI大模型:当工厂开始“深度思考”,一场静默的革命正在发生

凌晨三点&#xff0c;重庆某汽车零部件工厂的冲压产线突然响起刺耳的报警声。在过去&#xff0c;这意味着当班工程师需要一头扎进浩如烟海的故障手册与历史工单中&#xff0c;凭借经验和直觉摸索两小时以上。而此刻&#xff0c;系统在不到一秒的时间内&#xff0c;从后台调取了…

作者头像 李华
网站建设 2026/4/8 9:19:02

【强烈收藏】AI大模型发展史:从规则式AI到智能体应用的全方位解读

本文系统梳理了AI从诞生至今的发展历程&#xff0c;分为初生期(1956-1989)、成长期(1990-2016)和爆发期(2017年至今)三个阶段。从最初的规则式AI到基于机器学习的统计式AI&#xff0c;再到以Transformer架构为基础的大模型AI&#xff0c;技术不断演进。文章详细介绍了大模型、多…

作者头像 李华
网站建设 2026/4/12 11:34:44

AI Agent:2026年AI生态革命,开发者的收藏级技术指南

AI Agent 是2026年AI生态的核心概念&#xff0c;它指的是一个具备自主决策、规划和执行能力的数字实体&#xff0c;不再局限于简单的问答或生成式AI&#xff0c;而是能像人类员工一样处理复杂任务。简单来说&#xff0c;Agent 能理解用户意图、分解目标成步骤、调用外部工具或数…

作者头像 李华
网站建设 2026/4/4 6:59:01

换热站程序组态系统开发记录

换热站程序组态系统&#xff0c;2个循环泵&#xff0c;2个补水泵&#xff0c;循环泵与补水泵采用一用一备&#xff0c;按设置时间自动切换&#xff0c;CAD图纸 硬件&#xff1a;昆仑通泰触摸屏和西门子200smart供参考最近搞了个换热站程序组态系统&#xff0c;跟大家分享分享过…

作者头像 李华