-背景介绍
出于对安全的考虑,项目中要禁止浏览器的自动填充密码功能,经过和项目经理的一顿掰头(用户自己点的记住密码,有点过分了),最后在项目经理的一阵讨好下,本着对项目负责的精神,还是给他做了
实现思路
经过一顿搜索后大概找到了一下几个方案
- 设置autocomplete="off"
- 设置autocomplete="new-password",
- 在用户名密码输入框之前, 再写假的密码框让他填充
- 将两个input框分开,在中间加其他的输入框,设置定位或透明度将他隐藏
进过在google和edeg上测试,发现都不能满足要求,特别是之前记住过密码时,只要界面的password框聚焦就会弹出账号密码选择框,不管你怎么设置
既然问题再type="password"上,那没办法了,只能自己动手用type="text"的输入框模拟实现了,这样就不会被检测为password,也就不可能有填充了。
具体实现讲解
注意:下面的代码基于vue2+element
先上完整代码
<template>
<div>
{{ form.password }}
<el-form :model="form" :rules="rules" ref="loginform">
<el-form-item label="账号" prop="userName">
<el-input v-model="form.userName" type="text" placeholder="请输入账号" />
</el-form-item>
<el-form-item label="密码" prop="password">
<input
ref="passwordInput"
type="text"
v-model="password"
@input="inputPassword"
placeholder="请输入登录密码"
class="el-input__inner"
/>
</el-form-item>
</el-form>
<el-button @click="handleSubmit">登录</el-button>
</div>
</template>
<script>
export default {
data() {
return {
password: "",
form: {
userName: "",
password: "",
},
rules: {
userName: [
{ required: true, message: "用户不能为空", trigger: "blur" },
],
password: [
{ required: true, message: "密码不能为空", trigger: "blur" },
]
},
};
},
methods: {
inputPassword(e) {
let value = e.target.value; // 当前的值
let oldVal = this.form.password; // 之前的值
let passwordShow = ""; // 当前输入下需要显示的值,及n个*的字符串
let text = ""; // 当前input事件输入的值,如果是删除就没有值
// 当前input指针的位置,不一定是在最后
let startPoint = e.target.selectionStart;
let endPoint = e.target.selectionEnd;
if (!value) {
this.form.password = "";
this.password = "";
return;
}
let leftNum = 0; // 输入后左边保留多少
let rightNum = 0; // 输入后右边保留多少
let isLeft = true;
for (let i = 0; i < value.length; i++) {
passwordShow += "*";
if (value[i] == "*") {
if (isLeft) {
leftNum++;
} else {
rightNum++;
}
continue;
}
text += value[i];
isLeft = false;
}
if (text) {
this.form.password =
oldVal.slice(0, leftNum) +
text +
oldVal.slice(oldVal.length - rightNum);
} else {
// if (startPoint >= value.length) {
this.form.password =
oldVal.slice(0, startPoint) +
oldVal.slice(oldVal.length - leftNum - rightNum + startPoint);
// } else {
// this.form.password =
// oldVal.slice(0, startPoint) +
// oldVal.slice(oldVal.length - leftNum - rightNum + endPoint);
// }
}
this.password = passwordShow;
this.$nextTick(() => {
e.target.setSelectionRange(startPoint, startPoint);
});
},
handleSubmit() {
this.$refs.loginform.validate(valid => {
if (valid) {
// 登录
}
})
}
},
};
</script>
效果图
当密码框聚焦时不会有之前记住的账户密码弹窗了,登录后也不会提示你是否记住密码了
关键位置讲解
- 输入框
<el-form-item label="密码" prop="password">
<input
ref="passwordInput"
type="text"
v-model="password"
@input="inputPassword"
placeholder="请输入登录密码"
class="el-input__inner"
/>
</el-form-item>
为了彻底不显示账号密码弹框,只能用text的输入框去输入,在input事件中再去将输入置为*
- 输入后值的处理
- 输入值的拼接
- 删除值的处理(主要是非末尾删除)
逻辑图
if (text) {
this.form.password =
oldVal.slice(0, leftNum) +
text +
oldVal.slice(oldVal.length - rightNum);
} else {
this.form.password =
oldVal.slice(0, startPoint) +
oldVal.slice(oldVal.length - leftNum - rightNum + startPoint);
}
- 最后要把指针还原,默认会跳到最后
this.$nextTick(() => {
e.target.setSelectionRange(startPoint, startPoint);
});
待解决问题
- 项目就一个登录界面,就没封装成组件,可考虑封装下
- input的blur没触发校验,点击登录才有,不知道什么原因,可手动加个事件触发