这次通过这个个性化的输入框,给大家介绍一些容易忽略的知识点。(新手注意:本文的html采用的是jade,css采用的sass,js采用的vue)
一、效果
?大家先看一下效果动态图,思考一波,带着你的思考来看接下来的内容,可能效果更好一点。
二、需求
?当我们开始做一样东西的时候一定要先分析它的需求:
?*?当输入框获取焦点时,提示文字发生上移动画,同时下面线条产生动画;
?*?当输入框失去焦点时,并且未填写内容时,提示文字和线条恢复之前的状态。
?*?当输入框失去焦点时,填写内容时,状态不变。
三、结构
?看了上面的效果图,首先就是要确定html的结构:
div.item
input(type="text" name="card" id="card" placeholder="身份证" v-card="" maxlength="18")
label(for="card") Card
div.focusline
?这里唯一遗憾的是input不支持伪元素(::after、::before),所以不得不采用一个额外的div。
?这里额外提一下,maxlength 只能用于input的type为password和text的情况,所以不要再问为什么maxlength不起作用了。
四、表现
?其实对于上面所要实现的效果,我们完全可以通过JS来控制,但是一直在强调_表现(CSS)与行为(JS)分离_,所以我们完全通过CSS的特性解决表现上的问题,更加完美。但是并不是所有CSS属性浏览器多支持(这就尴尬了)。这里我要用的几个特性,大家最好在Chrome中实验。
?其实需求1与需求2是同一个需求,通过伪类focus和过渡属性就能搞定。
input:focus + label {
color: rgb(82,97,107);
transform: translate(10px, 0) scale(.9);
}
input:focus ~ div {
width: 100%;
}
?对于第三个需求,我们就得用一些新玩意了,第一个就是伪元素placeholder(_伪类采用: 而伪元素采用::_), 这里我们要隐藏placeholder,好显示我们的label:
input {
&:placeholder {
opacity: 0;
}
}
?我们知道当输入文字后,placeholder就不再显示了,所以这里来了一个伪类placeholder-shown(可以通过can i use 查一下它的兼容性):
input:not(:placeholder-shown) + label {
color: rgb(82,97,107);
transform: translate(10px, 0) scale(.9);
}
input:not(:placeholder-shown) ~ div {
width: 100%;
}
五、行为
?这里我还要唠叨一下,从上面可以看出这是一个身份证输入框,我们多知道身份证是由数字和字母,而且字母只出现在第18位,而且只能是字母x。所以我上面采用了text类型的输入框,为了让用户很好的输入,会出现这几种问题:
?*?切换为中文输入法时存在的问题;
?*?复制粘贴的问题;
?*?输入其他非法字符的处理。
?这里我们主要通过input、compositionstart、compositionend、paste四个事件解决。
let legalContent, //开启输入法之前的输入内容
LOCK = false; //是否开启中文输入法
el.addEventListener(‘compositionstart‘, (e) => {
/**
* --------------
* 开启中文输入法
* --------------
*/
legalContent = e.target.value; //保存中文输入法之前的内容
LOCK = true; //加上锁
}, false);
el.addEventListener(‘compositionend‘, (e) => {
/**
* ---------------------
* 结束中文输入法
* ---------------------
*/
e.target.value = legalContent;
LOCK = false; // 解锁
}, false);
el.addEventListener(‘input‘, (e) => {
const len = e.target.value.length;
/**
* 在中文触发时 不进行处理
* 当身份证号码少于18位时只能输入数字
* 当身份证号码为18位时可以输入数字和字母
*/
if (!LOCK) {
if (len <= 17) {
e.target.value = e.target.value.replace(/\D/,‘‘);
} else {
e.target.value = e.target.value.replace(/[^0-9Xx]/,‘‘);
}
}
}, false);
el.addEventListener(‘paste‘, (e) => {
/**
* ----------
* 粘贴
* ----------
*/
e.preventDefault(); //阻止默认事件
}, false);