v-input-limit

/*

    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)

    }

}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值