v-input-limit

javascript 复制代码
/*

    v-input-limit:price             金额

    v-input-limit:phone             电话

    v-input-limit:number            数字

    v-input-limit:negativePrice     负数金额

    v-input-limit:loginVerify       登录验证码

    v-input-limit:verify            短信验证码

    v-input-limit:idCard            身份证号

    v-input-limit="RegExp"          自定义验证规则

*/

export default {

    // 该指令会频发触发input事件,并且ctrl+z会失效,使用时请注意

    inserted(el, binding, vnode) {

        // 通过修饰符储备可用的正则

        const regObj = {

            price: /^(\d*|(\d+\.\d{0,2}))$/,

            phone: /^\d{0,11}$/,

            number: /^\d*$/,

            negativePrice: /^\-?(\d*|(\d+\.\d{0,2}))$/, //负数金额

            loginVerify: /^[0-9a-zA-Z]{0,4}$/,

            verify: /^\d{0,6}$/,

            idCard: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,//身份证号(15位、18位数字),最后一位是校验位,可能为数字或字符X

            allphone: /^[0-9\+\-]{0,14}$/ //电话+手机

        }

        // 要应用的正则表达式 优先binding.value

        let reg =

            binding.value && binding.value instanceof RegExp

                ? binding.value

                : binding.arg && regObj[binding.arg] ? regObj[binding.arg] : null


 

        // input输入事件

        el._inputHandle = function (e) {

            // 判断是否是用户行为

            if (

                e.isTrusted &&

                !(

                    !e.isComposing &&

                    e.inputType === 'insertCompositionText' && e.data

                )

            ) {

                // 判断正则匹配

                let isFalse = reg && !reg.test(e.target.value)

                // 如果匹配错误返回上次输入值

                el._input = isFalse ? el._input : e.target.value

                e.target.value = '' //重置中文输入法

                e.target.value = el._input // 重新赋值

                // 控制光标所在位置

                if (isFalse) {

                    // 输入内容不匹配,光标不动

                    e.target.selectionStart = el._start

                    e.target.selectionEnd = el._end

                } else {

                    // 判断inputType计算光标位置

                    // inputType类型 https://www.jc2182.com/javascript/javascript-html-dom-inputtype-event-attr.html

                    switch (e.inputType) {

                        case 'deleteContentForward': //delete

                        case 'deleteByDrag': //dropout

                        case 'deleteByCut': //cut

                            e.target.selectionStart = el._start

                            e.target.selectionEnd = el._start

                            break

                        case 'deleteContentBackward': //backspace

                            e.target.selectionStart =

                                el._start === el._end

                                    ? el._start - 1

                                    : el._start

                            e.target.selectionEnd =

                                el._start === el._end

                                    ? el._start - 1

                                    : el._start

                            break

                        case 'insertFromPaste': //粘贴

                        case 'insertFromDrop': //拖入

                            let dataTransfer =

                                e.dataTransfer ||

                                e.clipboardData ||

                                null

                            if (dataTransfer) {

                                let txt =

                                    dataTransfer.getData('text') || ''

                                e.target.selectionStart =

                                    el._start + txt.length

                                e.target.selectionEnd =

                                    el._start + txt.length

                            }

                            break

                        case 'insertText': //insert

                        case 'insertCompositionText': //中文输入法输入

                            e.target.selectionStart = el._start + 1

                            e.target.selectionEnd = el._start + 1

                            break

                        default:

                            break

                    }

                }

                // 发送input事件同步字符串

                let event = new InputEvent('input', {

                    isComposing: false,

                })

                e.target.dispatchEvent(event)

                // 中文下触发el-input input事件

                // if (e.isComposing) {

                //     // 中文时同步字符串--表示内容以输入完毕

                //     let event = new CompositionEvent('input', {

                //         isComposing: false,

                //         data: ''

                //     })

                //     e.target.dispatchEvent(event)

                //     console.log

                // } else {

                //     // 同步字符串

                //     let event = new InputEvent('input')

                //     e.target.dispatchEvent(event)

                // }

            } else {

                return

            }

        }

        // input输入前事件

        el._beforeinputHandle = function (e) {

            el._input =

                reg && !reg.test(e.target.value) ? '' : e.target.value

            el._start = e.target.selectionStart

            el._end = e.target.selectionEnd

        }

        // input以及el-input可使用本指令

        if (

            vnode.tag === 'input' ||

            (vnode.componentOptions &&

                vnode.componentOptions.tag === 'el-input')

        ) {

            // 监听input事件

            el.addEventListener('input', el._inputHandle)

            // 监听inputbefore事件 给el._input赋值(未知的兼容性)

            el.addEventListener('keydown', el._beforeinputHandle)

            // 阻止事件传播(firefox)

            el.addEventListener('drop', e => {

                e.stopPropagation()

            })

        } else {

            console.warn('该指令应应用于input或el-input')

        }

    },

    unbind(el, binding) {

        // 取消事件绑定

        el._inputHandle &&

            el.removeEventListener('input', el._inputHandle)

        el._beforeinputHandle &&

            el.removeEventListener('beforeinput', el._beforeinputHandle)

    }

}

在main.js中全局注册

javascript 复制代码
//引入自定义指令
import * as directives from "./directives";
//注册指令
Object.keys(directives).forEach((k) => Vue.directive(k, directives[k]));

组件中直接使用

javascript 复制代码
<el-input
                      v-model.trim="item.giveHour"
                      placeholder="请输入"
                      clearable
                      v-inputLimit:number
                    >
                    </el-input>
相关推荐
killerbasd2 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
橘子编程3 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
叫我一声阿雷吧4 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint
大家的林语冰4 小时前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
jiayong234 小时前
第 8 课:开始引入组合式函数
前端·javascript·学习
天若有情6735 小时前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
M ? A6 小时前
Vue 迁移 React 实战:VuReact 一键自动化转换方案
前端·vue.js·经验分享·react.js·开源·自动化·vureact
yuki_uix6 小时前
重排、重绘与合成——浏览器渲染性能的底层逻辑
前端·javascript·面试
Burt6 小时前
我的 2026 全栈选型:Vue3 + Elysia + Bun + AlovaJS
vue.js·全栈·bun
止观止6 小时前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext