vue设置输入框输入长度_基于vue的限制输入框可输入字节数的解决方案
2018年07月11日
基于vue的限制输入框可输入字节数的解决方案
需求:input输入框输入上限4个字节、达到上限则不能继续输入,其中1个英文表示1个字节、1个中文表示2个字节。
看到这个需求,第一个想到的就是input元素的maxlength属性。
MDN对input的maxlength属性的说明是:
如果 type 的值是 text, email, search, password, tel, 或 url,那么这个属性指明了用户最多可以输入的字符个数(按照Unicode编码方式计数);对于其他类型的输入框,该属性被忽略。它可以大于 size 属性的值。如果不指定这个属性,那么用户可以输入任意多的字符。如果指定为一个负值,那么元素表现出默认行为,即用户可以输入任意多的字符。本属性的约束规则,仅在元素的 value 属性发生变化时才会执行。译者注:ie10+
从中我们可以得知两个有用信息:
maxlength可以用来限制输入长度;
maxlength是按字符数进行限制的,不能区分中英文。
根据这两个信息,我们得到了实现此需求的基本方案:
在用户输入之后计算输入内容的字节数和剩余可输入字节数,并动态地改变input元素的maxlength属性值。
计算输入内容的字节数
将输入内容的每一个中文字符替换成两个英文字符,计算其字符长度:
// 返回字符串str的长度,其中中文占2个长度单位,英文等字符占1个长度单位
let length = (str) => {
var r = /[^\x00-\xff]/g
return str.replace(r, 'mm').length
}
动态地改变maxlength值
思考解决方法过程中,分别实现过 通过@input事件触发方法来修改maxlength、把处理方法放到mixin里、封装一个处理方法的指令 3种方式,考虑可移植性及修改作用域字段的可行性,最终采用指令方式。
下面对主要逻辑进行说明:
maxlength:input元素maxlength属性值
limit:限制字节数
中文多消耗的字节数中文字符个数maxlength = limit - 中文多消耗的字节数 = limit - 中文字符个数
当连续输入的内容的字节数超过limit时,需要对内容进行截断:
截断长度 = 一个一个输入的非中文字符串长度 + 允许输入的中文字符串长度 = 非中文字符长度 + Math.floor((limit - 非中文字符所占字节数) / 2)
截断后内容 = 截断前内容.substring(0, 截断长度)
当在两个非中文之间(非末尾)输入超过限制的中文时,截取长度会多1个字节,需要再次校准输入内容:
校准后内容 = 校准前内容.substring(0, 截断长度 - 1)
vue自定义指令的钩子update是在VNode更新时调用,所以我们的处理方法在update钩子中进行;
vue自定义指令钩子函数会被传入参数el、binding、vnode、oldVnode。我们可以通过el拿到指定绑定的DOM;通过binding拿到指令的绑定值和传入的参数等等;通过vnode可以拿到vue编译生成的虚拟节点,其中vnode.context是虚拟节点上下文、也就是this,通过它我们可以改变指令所在组件data的任一变量。
其他方案及其缺陷
input v-model 使用 computed
export default {
data () {
return {
contentStore: ''
}
},
computed: {
content: {
get () {
return this.contentStore
},
set (val) {
this.contentStore = maxlength(val, 4) // maxlength是截取字符串方法
}
}
}
}
问题:虽然变量长度被限制了,但输入框仍可继续输入。
打印input元素的value,得到:
双向数据绑定失效了。
从v-model双向数据绑定原理入手
方法1中双向数据绑定失效了,那么我们来研究下input双向数据绑定的实现原理,看看能否找到突破口。
input的v-model只是一个简化的指令,它的双向数据绑定原理如下:
msg = e.target.value">
msg = e.target.value">
改写双向数据绑定方法:
methods: {
maxlengthInput (e) {
this.contentStore = maxlength(e.target.value, 4) // maxlength是截取字符串方法
}
}
结果和方法1一样,输入框仍可继续输入。
这里input的value是根据contentStore进行改变的,那直接修改DOM是否可行呢?
直接修改DOM的value值
在方法2的基础上,修改maxlengthInput方法,通过DOM操作来直接修改input的value,并打印出input的value进行观察:
methods: {
maxlengthInput (e) {
let value = maxlength(e.target.value, 4)
this.contentStore = value
document.querySelector('.el-input__inner').value = value
console.log(document.querySelector('.el-input__inner').value)
}
}
根据打印出来的内容可以看到,实际上input的value被改变了,而输入框内仍可正常输入,原因可能是element-ui的处理顺序问题(用原生input元素没有这个问题),那我们把dom赋值操作延后到下一个tick:
maxlengthInput (e) {
let value = maxlength(e.target.value, 4)
this.contentStore = value
setTimeout(() => {
document.querySelector('.el-input__inner').value = value
console.log(document.querySelector('.el-input__inner').value)
}, 0)
}
结果是可行的:
所以结束了吗?来输入中文试试:
中文输入法的每个拼音字母都被认为是一个有效的输入,这个缺陷是致命的。
compositionend事件
输入中文时,会先后触发compositionstart(输入中文前)、compositionend(中文输入完成后)事件。所以可以利用compositionend事件解决方法3的问题。
但是,删除输入内容时是无法触发compositionend事件的,那么,就需要同时监听input事件。
input事件会比compositionend事件先触发,所以会出现方法3的无法输入中文的问题,不过只要把input事件处理延迟到compositionend之后(比如用setTimeout),这个问题也可以解决。随之而来的问题就是输入非中文字符时,input事件处理也会延迟,用户体验不太友好。
总结
对于区分中英文来限制输入框输入长度的需求,利用input元素的maxlength属性是比较便利和可行的方式;使用vue自定义指令可以提高方法的可用性(再把指令封装成插件,可以很大地提高方法的可移植性)。
当然,vue自定义指令方法有一个问题,当在非末尾输入超过limit的内容时,会截断末尾的字符、而不是截断正在输入的内容。解决这个问题需要比较输入前和输入后的字符串、再把diff出的字符串截断掉。虽然这个问题可以解决,但性价比不高,对于当前的需求也没有解决的必要。
参考
vue设置输入框输入长度_基于vue的限制输入框可输入字节数的解决方案相关推荐
- vue 移动到图片浮动_基于Vue实现拖拽升级(九宫格拖拽)
前言 在本文中将会用Vue完成九宫格拖拽效果,同时介绍一下网格布局.具体代码以及demo可以点以下超链接进入 效果实例 Demo 简单了解Grid布局(网格布局) 什么是网格布局 CSS网格布局(又称 ...
- vue 文字上下循环滚动_基于 Vue 无缝滚动组件Vue-Seamless-Scroll
今天给小伙伴们推荐一款超棒的Vue无缝滚动组件VueSeamlessScroll. vue-seamless-scroll 基于 vue.js 构建的简单实用的无缝滚动组件.满足丰富的配置需求,支持上 ...
- 移动端vue实现部门结构功能_基于Vue的组织架构树组件
由于公司业务需求,需要开发一个展示组织架构的树组件(公司的项目是基于Vue).在GitHub上找了半天,这类组件不多,也没有符合业务需求的组件,所以决定自己造轮子! 分析 既然是树,那么每个节点都应该 ...
- 移动端vue实现部门结构功能_基于Vue制作组织架构树组件
编程之家收集整理的这篇文章主要介绍了基于Vue制作组织架构树组件,编程之家小编觉得挺不错的,现在分享给大家,也给大家做个参考. 由于公司业务需求,需要开发一个展示组织架构的树组件(公司的项目是基于Vu ...
- vue设置textarea最大字数_【Vue 学习】 Vue常用系统指令
1 v-on 指令 1.1 v-on:click 1.2 v-on:keydown 1.3 v-on:mouseover 1.4 事件修饰符 1.5 按键修饰符 2 v-text .v-html.v- ...
- 在vue中实现picker样式_基于Vue实现timepicker
主要用到的还是Vue的基本知识而已,不过要想到的细节很多. 先放效果,点击上框,显示timepicker.而且可以根据点击的是时还是分来改变圆盘的数字. 这里我用了两个组件,和,这里的时和分的数值我挂 ...
- vue 移动到图片浮动_基于Vue实现图片在指定区域内移动
当图片比要显示的区域大时,需要将多余的部分隐藏掉,我们可以通过绝对定位来实现,并通过动态修改图片的left值和top值从而实现图片的移动.具体实现效果如下图,如果我们移动的是div 实现思路相仿. 此 ...
- vue 移动端头像裁剪_基于vue的移动端图片裁剪压缩处理
前端时间做Vue项目的时候,要用到图片压缩处理,网上查阅了资料后,发现并不能满足实际的业务需求:于是,自己结合网上的资料写了一个,有兴趣的小伙伴不妨试试~ 废话不多说,先上效果图,无图无真相嘛~ 效果 ...
- 在vue中实现picker样式_基于vue的颜色选择器vue-color-picker
/** * author : alex * email : 961163829@qq.com*/exportdefault{ props:{/*由父组件传递的默认颜色*/defaultColor:{ ...
最新文章
- 第三十一篇:SOUI布局之相对于特定兄弟窗口
- ASP.NET 3.5技术专题发布
- python 链栈及基本操作
- wordpress语言文件.po.pot.mo简介及汉化
- 更新:让UpdatePanel支持上传文件
- 实现拼团_生鲜商家如何使用微信拼团小程序做水果生鲜拼团活动?
- ubuntu的home目录下,Desktop等目录消失不见
- php可变变量讲解,PHP可变变量实例详解
- java学习(58):私有内部类后访问
- HA机制的大数据集群的搭建过程
- 求出数组中超过一半的数
- 手游加速器原理分析和代码实现
- fedora安装字体
- Mac电脑专业音乐制作Logic Pro X中文
- 点餐小程序的数据库设计以及系统实现
- linux 极点五笔,Linux 安装ibus极点五笔输入法备忘录
- 小tips:页面滚动到关闭时的位置与不滚动
- Dubbo-Zookeeper注册中心;监控中心
- 【tph-yolov5】tph-Yolov5的Pytorch环境配置和运行错误记录
- Python利用Scrapy爬取智联招聘和前程无忧的招聘数据