vue自定义组件表单验证(vue实现一个6个输入框的验证码输入组件)

vue自定义组件表单验证(vue实现一个6个输入框的验证码输入组件)(1)

作者:jsoncode

转发链接:https://segmentfault.com/a/1190000023041

前言

要实现的功能:

完全和单输入框一样的操作,甚至可以插入覆盖:

1,限制输入数字

2,正常输入

3,backspace删除

4,paste任意位置粘贴输入

5,光标选中一个数字,滚轮可以微调数字大小,限制0-9

6,123|456 自动覆盖光标后输入的字符,此时光标在3后,继续输入111,会得到123111,而不用手动删除456

7,封装成vue单文件组件,方便任意调用。

vue自定义组件表单验证(vue实现一个6个输入框的验证码输入组件)(2)

演示图

模板代码

<template> <div class="input-box"> <div class="input-content" @keydown="keydown" @keyup="keyup" @paste="paste" @mousewheel="mousewheel" @input="inputEvent"> <input max="9" min="0" maxlength="1" data-index="0" v-model.trim.number="input[0]" type="number" ref="firstinput"/> <input max="9" min="0" maxlength="1" data-index="1" v-model.trim.number="input[1]" type="number"/> <input max="9" min="0" maxlength="1" data-index="2" v-model.trim.number="input[2]" type="number"/> <input <input max="9" min="0" maxlength="1" data-index="4" v-model.trim.number="input[4]" type="number"/> <input max="9" min="0" maxlength="1" data-index="5" v-model.trim.number="input[5]" type="number"/> </div> </div> </template>

实现了键盘的keydown/keyup/paste/input和鼠标滚轮mousewheel事件

使用了6个输入框的方案来实现。

样式部分:使用了scss模式

<style scoped lang="scss"> .input-box { .input-content { width: 512px; height: 60px; display: flex; align-items: center; justify-content: space-between; input { color: inherit; font-family: inherit; border: 0; outline: 0; border-bottom: 1px solid #919191; height: 60px; width: 60px; font-size: 44px; text-align: center; } } input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { appearance: none; margin: 0; } } </style>

具体实现逻辑:主要实现以上几个键盘事件操作。

<script> export default { data() { return { // 存放粘贴进来的数字 pasteResult: [], }; }, props: ['code'], computed: { input() { // 计算输入框的值 if (this.code && Array.isArray(this.code) && this.code.length === 6) { return this.code; } else if (/^\d{6}$/.test(this.code.toString())) { return this.code.toString().split(''); } else if (this.pasteResult.length === 6) { return this.pasteResult; } else { return new Array(6); } } }, methods: { // 解决一个输入框输入多个字符 inputEvent(e) { var index = e.target.dataset.index * 1; var el = e.target; this.$set(this.input, index, el.value.slice(0, 1)) }, keydown(e) { var index = e.target.dataset.index * 1; var el = e.target; if (e.key === 'Backspace') { if (this.input[index].length > 0) { this.$set(this.input, index, '') } else { if (el.previousElementSibling) { el.previousElementSibling.focus() this.$set(this.input, index - 1, '') } } } else if (e.key === 'Delete') { if (this.input[index].length > 0) { this.$set(this.input, index, '') } else { if (el.nextElementSibling) { this.$set(this.input, index = 1, '') } } if (el.nextElementSibling) { el.nextElementSibling.focus() } } else if (e.key === 'Home') { el.parentElement.children[0] && el.parentElement.children[0].focus() } else if (e.key === 'End') { el.parentElement.children[this.input.length - 1] && el.parentElement.children[this.input.length - 1].focus() } else if (e.key === 'ArrowLeft') { if (el.previousElementSibling) { el.previousElementSibling.focus() } } else if (e.key === 'ArrowRight') { if (el.nextElementSibling) { el.nextElementSibling.focus() } } else if (e.key === 'ArrowUp') { if (this.input[index] * 1 < 9) { this.$set(this.input, index, (this.input[index] * 1 1).toString()); } } else if (e.key === 'ArrowDown') { if (this.input[index] * 1 > 0) { this.$set(this.input, index, (this.input[index] * 1 - 1).toString()); } } }, keyup(e) { var index = e.target.dataset.index * 1; var el = e.target; // 解决输入e和无法删除e的问题 感谢一群网友 https://segmentfault.com/u/nanzk8fl 的指正 el.value=el.value.replace(/1/g,''); if (/Digit|Numpad/i.test(e.code)) { this.$set(this.input, index, e.code.replace(/Digit|Numpad/i, '')); el.nextElementSibling && el.nextElementSibling.focus(); if (index === 5) { if (this.input.join('').length === 6) { document.activeElement.blur(); this.$emit('complete', this.input); } } } else { if (this.input[index] === '') { this.$set(this.input, index, ''); } } }, mousewheel(e) { var index = e.target.dataset.index; if (e.wheelDelta > 0) { if (this.input[index] * 1 < 9) { this.$set(this.input, index, (this.input[index] * 1 1).toString()); } } else if (e.wheelDelta < 0) { if (this.input[index] * 1 > 0) { this.$set(this.input, index, (this.input[index] * 1 - 1).toString()); } } else if (e.key === 'Enter') { if (this.input.join('').length === 6) { document.activeElement.blur(); this.$emit('complete', this.input); } } }, paste(e) { // 当进行粘贴时 e.clipboardData.items[0].getAsString(str => { if (str.toString().length === 6) { this.pasteResult = str.split(''); document.activeElement.blur(); this.$emit('complete', this.input); // 恢复缓冲区 this.pasteResult = []; } else { // 如果粘贴内容不合规,清除所有内容 this.input = new Array(6) } }) } }, mounted() { // 等待dom渲染完成,在执行focus,否则无法获取到焦点 this.$nextTick(() => { this.$refs.firstinput.focus() }) }, } </script>

如果你发现了bug,或者有优化空间,欢迎你的指正和建议。我会随时更新到源代码当中,分享给大家。

推荐Vue学习资料文章:

《一用惊人的Vue实践技巧「值得推荐」》

《Vue常见的面试知识点汇总(上)「附答案」》

《Vue常见的面试知识点汇总(下)「附答案」》

《Kbone原理详解与小程序技术选型》

《为什么我不再用Vue,改用React?》

《让Jenkins自动部署你的Vue项目「实践」》

《20个免费的设计资源 UI套件背景图标CSS框架》

《Deno将停止使用TypeScript,并公布五项具体理由》

《前端骨架屏都是如何生成的》

《Vue原来可以这样写开发效率杠杠的》

《用vue简单写一个音乐播放组件「附源码」》

《为什么Vue3.0不再使用defineProperty实现数据监听?》

《「干货」学会这些Vue小技巧,可以早点下班和女神约会》

《探索 Vue-Multiselect》

《细品30张脑图带你从零开始学Vue》

《Vue后台项目中遇到的技术难点以及解决方案》

《手把手教你Electron Vue实战教程(五)》

《手把手教你Electron Vue实战教程(四)》

《手把手教你Electron Vue实战教程(三)》

《手把手教你Electron Vue实战教程(二)》

《手把手教你Electron Vue实战教程(一)》

《收集22种开源Vue模板和主题框架「干货」》

《如何写出优秀后台管理系统?11个经典模版拿去不谢「干货」》

《手把手教你实现一个Vue自定义指令懒加载》

《基于 Vue 和高德地图实现地图组件「实践」》

《一个由 Vue 作者尤雨溪开发的 web 开发工具—vite》

《是什么让我爱上了Vue.js》

《1.1万字深入细品Vue3.0源码响应式系统笔记「上」》

《1.1万字深入细品Vue3.0源码响应式系统笔记「下」》

《「实践」Vue 数据更新7 种情况汇总及延伸解决总结》

《尤大大细说Vue3 的诞生之路「译」》

《提高10倍打包速度工具Snowpack 2.0正式发布,再也不需要打包器》

《大厂Code Review总结Vue开发规范经验「值得学习」》

《Vue3 插件开发详解尝鲜版「值得收藏」》

《带你五步学会Vue SSR》

《记一次Vue3.0技术干货分享会》

《Vue 3.x 如何有惊无险地快速入门「进阶篇」》

《「干货」微信支付前后端流程整理(Vue Node)》

《带你了解 vue-next(Vue 3.0)之 炉火纯青「实践」》

《「干货」Vue 高德地图实现页面点击绘制多边形及多边形切割拆分》

《「干货」Vue Element前端导入导出Excel》

《「实践」Deno bytes 模块全解析》

《细品pdf.js实践解决含水印、电子签章问题「Vue篇」》

《基于vue element的后台管理系统解决方案》

《Vue仿蘑菇街商城项目(vue koa mongodb)》

《基于 electron-vue 开发的音乐播放器「实践」》

《「实践」Vue项目中标配编辑器插件Vue-Quill-Editor》

《基于 Vue 技术栈的微前端方案实践》

《消息队列助你成为高薪 Node.js 工程师》

《Node.js 中的 stream 模块详解》

《「干货」Deno TCP Echo Server 是怎么运行的?》

《「干货」了不起的 Deno 实战教程》

《「干货」通俗易懂的Deno 入门教程》

《Deno 正式发布,彻底弄明白和 node 的区别》

《「实践」基于Apify node react/vue搭建一个有点意思的爬虫平台》

《「实践」深入对比 Vue 3.0 Composition API 和 React Hooks》

《前端网红框架的插件机制全梳理(axios、koa、redux、vuex)》

《深入Vue 必学高阶组件 HOC「进阶篇」》

《深入学习Vue的data、computed、watch来实现最精简响应式系统》

《10个实例小练习,快速入门熟练 Vue3 核心新特性(一)》

《10个实例小练习,快速入门熟练 Vue3 核心新特性(二)》

《教你部署搭建一个Vue-cli4 Webpack移动端框架「实践」》

《2020前端就业Vue框架篇「实践」》

《详解Vue3中 router 带来了哪些变化?》

《Vue项目部署及性能优化指导篇「实践」》

《Vue高性能渲染大数据Tree组件「实践」》

《尤大大细品VuePress搭建技术网站与个人博客「实践」》

《10个Vue开发技巧「实践」》

《是什么导致尤大大选择放弃Webpack?【vite 原理解析】》

《带你了解 vue-next(Vue 3.0)之 小试牛刀【实践】》

《带你了解 vue-next(Vue 3.0)之 初入茅庐【实践】》

《实践Vue 3.0做JSX(TSX)风格的组件开发》

《一篇文章教你并列比较React.js和Vue.js的语法【实践】》

《手拉手带你开启Vue3世界的鬼斧神工【实践】》

《深入浅出通过vue-cli3构建一个SSR应用程序【实践】》

《怎样为你的 Vue.js 单页应用提速》

《聊聊昨晚尤雨溪现场针对Vue3.0 Beta版本新特性知识点汇总》

《【新消息】Vue 3.0 Beta 版本发布,你还学的动么?》

《Vue真是太好了 壹万多字的Vue知识点 超详细!》

《Vue Koa从零打造一个H5页面可视化编辑器——Quark-h5》

《深入浅出Vue3 跟着尤雨溪学 TypeScript 之 Ref 【实践】》

《手把手教你深入浅出vue-cli3升级vue-cli4的方法》

《Vue 3.0 Beta 和React 开发者分别杠上了》

《手把手教你用vue drag chart 实现一个可以拖动 / 缩放的图表组件》

《Vue3 尝鲜》

《总结Vue组件的通信》

《Vue 开源项目 TOP45》

《2020 年,Vue 受欢迎程度是否会超过 React?》

《尤雨溪:Vue 3.0的设计原则》

《使用vue实现HTML页面生成图片》

《实现全栈收银系统(Node Vue)(上)》

《实现全栈收银系统(Node Vue)(下)》

《vue引入原生高德地图》

《Vue合理配置WebSocket并实现群聊》

《多年vue项目实战经验汇总》

《vue之将echart封装为组件》

《基于 Vue 的两层吸顶踩坑总结》

《Vue插件总结【前端开发必备】》

《Vue 开发必须知道的 36 个技巧【近1W字】》

《构建大型 Vue.js 项目的10条建议》

《深入理解vue中的slot与slot-scope》

《手把手教你Vue解析pdf(base64)转图片【实践】》

《使用vue node搭建前端异常监控系统》

《推荐 8 个漂亮的 vue.js 进度条组件》

《基于Vue实现拖拽升级(九宫格拖拽)》

《手摸手,带你用vue撸后台 系列二(登录权限篇)》

《手摸手,带你用vue撸后台 系列三(实战篇)》

《前端框架用vue还是react?清晰对比两者差异》

《Vue组件间通信几种方式,你用哪种?【实践】》

《浅析 React / Vue 跨端渲染原理与实现》

《10个Vue开发技巧助力成为更好的工程师》

《手把手教你Vue之父子组件间通信实践讲解【props、$ref 、$emit】》

《1W字长文 多图,带你了解vue的双向数据绑定源码实现》

《深入浅出Vue3 的响应式和以前的区别到底在哪里?【实践】》

《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》

《基于Vue/VueRouter/Vuex/Axios登录路由和接口级拦截原理与实现》

《手把手教你D3.js 实现数据可视化极速上手到Vue应用》

《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【上】》

《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【中】》

《吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【下】》

《Vue3.0权限管理实现流程【实践】》

《后台管理系统,前端Vue根据角色动态设置菜单栏和路由》

作者:jsoncode

转发链接:https://segmentfault.com/a/1190000023041401

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页