前言:

网站中的input输入框使用非常广泛,因业务场景不同需要对输入框做合法性校验或限制输入,比如电话号码、邮件、区号、身份证号等。input框的不合法内容主要有两种方式处理:1.用户输入内容后,通过规则验证告知用户不合法,2.禁止输入不符合规则字符。下面基于第2种情况,针对Vue中的input控件通过自定义指令(directive),使用正则表达式限制input控件的输入。

工作流程:

input控件绑定v-model ---> 通过自定义指令(v-restrict)设定验证的正则表达式 ---> 监控控件的keyup、keydown、paste事件,验证字符合法性 ---> 替换非法字符 ---> 替换后的结果更新绑定到v-model的变量里

控件元素代码:

<v-text-field label="Test"
v-model="testtext"
v-restrict="/[^a-zA-Z0-9]/g"
</v-text-field>

自定义指令(directive)代码:

import Vue from "vue";

Vue.directive("restrict", {
bind(el, binding) {
const target =
el instanceof HTMLInputElement ? el : el.querySelector("input");
target.addEventListener("keydown", e => {
if (binding.value) {
// Regex check
if (binding.value.test(e.target.value)) {
e.target.value = e.target.value.replace(binding.value, "");
e.target.dispatchEvent(new Event("input"));//调用input事件使vue v-model绑定更新,下面相同
}
}
});
target.addEventListener("paste", e => {
if (binding.value) {
// Regex check
if (binding.value.test(e.target.value)) {
e.target.value = e.target.value.replace(binding.value, "");
e.target.dispatchEvent(new Event("input"));
}
}
});
target.addEventListener("keyup", e => {
if (binding.value) {
// Regex check
if (binding.value.test(e.target.value)) {
e.target.value = e.target.value.replace(binding.value, "");
e.target.dispatchEvent(new Event("input"));
}
}
});
} // end bind
}); // end directive

v-model本质及实现原理

通过下面两行代码给input输入框绑定值并添加事件钩子:

这实际上就是 input 实现 v-model 的精髓,通过修改 AST 元素,给 el 添加一个 prop,相当于我们在 input 上动态绑定了 value又给 el 添加了事件处理,相当于在 input 上绑定了 input 事件,其实转换成模板如下:

其实就是动态绑定了 input 的 value 指向了 messgae 变量,并且在触发 input 事件的时候去动态把 message 设置为目标值,这样实际上就完成了数据双向绑定了,所以说 v-model 实际上就是语法糖。

通过下面的window.getEventListeners(obj)就能看出在这个控件上绑定了input方法,当通过监听事件修改e.target.value时,并未调用input方法,所以v-model的值没有变化,需要通过代码(e.target.dispatchEvent(new Event("input"));)手动触发input事件。
 
下面代码可以验证e.target.value变化与v-model的联动变化过程:
Vue template code:
<v-text-field label="Test"
v-model="testtext"
@keyup="testkeyup($event)">
<v-icon medium
slot="append"
@click.native="test()">save</v-icon>
</v-text-field> Vue script code:
data{testtext: "zsl"}
methods: {
test() {
this.testtext += "a";
},
testkeyup(e) {
e.target.value += "b";
var eventb = new Event("input");
e.target.dispatchEvent(eventb);
console.log(
"e.target.value: " +
e.target.value +
" | this.testtext: " +
this.testtext
);
}
}

获取某元素绑定的所有事件(Listener)

通过Chrome中,在Console窗口里,通过window.getEventListeners(obj)获取某个元素绑定的所有事件(listener)

e.target.value的修改(change)不会自动调用vue的input方法,通过dispatchEvent的方式手动调用

e.target.dispatchEvent(new Event("input"));

Vue input 控件: 通过自定义指令(directive)使用正则表达式限制input控件的输入的更多相关文章

  1. vue从入门到进阶:自定义指令directive,插件的封装以及混合mixins(七)

    一.自定义指令directive 除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令.注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件.然而,有的 ...

  2. angularjs自定义指令Directive

    今天学习angularjs自定义指令Directive.Directive是一个非常棒的功能.可以实现我们自义的的功能方法. 下面的例子是演示用户在文本框输入的帐号是否为管理员的帐号"Adm ...

  3. angularjs - 自定义指令(directive)

    自定义指令(directive) 使用 .directive 函数来添加自定义的指令. 要调用自定义指令,HTML 元素上需要添加自定义指令名. 例子:使用驼峰法来命名一个指令, demoDirect ...

  4. vue.js实现内部自定义指令和全局自定义指令------directive

    在Vue中,我们平时数据驱动视图时候,内部自带的指令有时候解决不了一些需求,这时候,Vue给我们一个很好用的东东 directive 这个单词是我们写自定义指令的关键字哦 之定义指令为我们提供了几个钩 ...

  5. vue 自定义指令directive

    //自定义指令:directive 的传参--可以数据也可以是字符串 Vue.directive('scroll', function (binding) { window.addEventListe ...

  6. vue自定义指令(Directive中的clickoutside.js)的理解

    阅读目录 vue自定义指令clickoutside.js的理解 回到顶部 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: vue自定义指令 一般在需要 DOM 操 ...

  7. Vue(九)---自定义指令(directive )

    1.无参数 自定义指令的方式:1. 使用Vue.directive 来自定义2. 第一个参数就是 指令名称 xart3. el 表示当前的html dom对象4. 在方法体内就可以通过 innerHT ...

  8. vue.js之过滤器,自定义指令,自定义键盘信息以及监听数据变化

    一.监听数据变化 1.监听数据变化有两种,深度和浅度,形式如下: vm.$watch(name,fnCb); //浅度 vm.$watch(name,fnCb,{deep:true}); //深度监视 ...

  9. VUe键盘修饰符及自定义指令获取焦点

    首先需要在keyup事件之后. 修饰符 来绑定事件 <body> <div class="box"> <!-- 这里的 @keyup.enter=&q ...

随机推荐

  1. PHP中将二维数组 转换成字符串

    function arr_to_str($arr) { $t ='' ; foreach ($arr as $v) { $v = join(",",$v); // 可以用implo ...

  2. Height、clientHeight、scrollHeight、offsetHeight 、scrollTop、offsetTop

    Height 返回当前文档中的<body>元素的高度 clientHeight 对于没有定义CSS或者内联布局盒子的元素为0,否则,它是元素内部的高度(单位像素),包含内边距,但不包括水平 ...

  3. Oracle自动化安装脚本-part03-亲试ok

     此为 软件包配置文件 software.conf [CentOS6] binutils-2.20.51.0.2-5.11.el6 (x86_64) compat-libcap1-1.10-1 (x8 ...

  4. [cf1138BCircus][枚举,列等式]

    https://codeforc.es/contest/1138/problem/B B. Circus time limit per test 1 second memory limit per t ...

  5. SVG矢量绘图 path路径详解(贝塞尔曲线及平滑)

    以二次贝塞尔曲线的公式为例: js函数: //p0.p1.p2三个点,其中p0为起点,p2为终点,p1为控制点 //它们的坐标用数组表示[x,y] //t的范围是0-1 function qBerzi ...

  6. Mac工具库

    1.文件传输工具 CyberDuck 2.解压缩工具 The Unarchiver 3. 录屏工具 LICEcap 4. 命令框工具 Go2Shell / iTerm 5. 提醒事项 OmniFocu ...

  7. centos安装JDK、Tomcat、mysql

    1.下载 jdk-8u131-linux-x64.tar.gz 下载地址: https://pan.baidu.com/s/1o8LW9eE 密码: miva 2.下载 apache-tomcat-8 ...

  8. CF786C Till I Collapse 整体二分+根号分治

    题意:对于一个序列,假如说一个区间内最多能包含 $k$ 个不同的数,那么这个序列最少会被划分成几个区间 $?$ 输出 $k$ 为 $1\sim n$ 的答案. 我们每次选区间一定是贪心地将这个区间选地 ...

  9. 【组合数学】OI内的排列与组合(简单版)

    §1基本原理 △让我们来看下面问题: 从甲地到乙地,可以乘火车,也可以乘汽车,还可以乘轮船.一天中,火车有4班,汽车有2班,轮船有3班.那么,一天中乘坐这些交通工具从甲地到乙地共有多少种不同走法?△分 ...

  10. 线段树QWQ

    一直没碰过线段树,个人认为好长好难,不过这几天做题遇到了裸的线段树的题,TAT. 线段树我理解就是把二叉树的左右节点现在分别看成是两个区间. 那么现在这两个区间的端点怎么存放?怎么能够把这个区间里的数 ...