禁止浏览器记住明码、主动填写明码,反对明文暗文显示明码
应用办法:父组件中引入handPwd.vue组件
父组件应用:
<el-form ref="form" :model="form" :rules="rules" > <el-form-item label="明码" key="password" prop="password"> <hand-password ref="handPassword" inputId="handPassword-password" @inputPwd="inputPassword" :needValidatePwd="false" ></hand-password> <!-- <el-input type="password" v-model="form.password" placeholder="明码" clearable ></el-input> --> </el-form-item> </el-form>import handPassword from '@/components/common/handPassword.vue'components: { handPassword },data(){ return { form:{ password:'' }, rules:{ password: [ { required: true, message: '明码不能为空', trigger: 'blur' }, { pattern: /^[^\s\u4e00-\u9fa5]+$/, message: '不容许输出空格、中文等特殊符号' } ] } }},methods:{ inputPassword(val) { this.form.password = val this.$refs.form.validateField('password') }}
handPwd.vue
<template> <div> <div :class="['el-input', 'el-input--suffix', prefixIconName != '' ? 'el-input--prefix' : '']"> <!-- 判断account是否为admin,是为了给开发留个后门,方便使用浏览器记住明码哈哈 --> <!-- 禁止复制、粘贴、剪切 --> <input :type="account == 'admin' ? 'password' : 'text'" autocomplete="off" :id="inputId" v-model="secretPwd" @input="inputPassword" @copy.prevent="() => {}" @paste.prevent="() => {}" @cut.prevent="() => {}" :placeholder="placeholder" :maxlength="maxLength" class="el-input__inner" :style="{ 'padding-right': clearPwd != '' ? '56px' : '30px' }" /> <span v-show="prefixIconName != ''" class="el-input__prefix" ><i :class="prefixIconName"></i ></span> <span class="el-input__suffix"> <span class="el-input__suffix-inner"> <i v-show="secretPwd !== ''" @click="inputPassword({ target: { value: '' } })" class="el-input__icon el-icon-circle-close" style="cursor: pointer;vertical-align: middle;" ></i> <svg-icon v-if="showPwd" @click="handleShowPwd" iconClass="明文" class="el-input__icon el-icon-view" style="cursor: pointer;height: 32px;font-size: 12px;color: #C0C4CC;vertical-align: middle;margin-right: 6px;" /> <svg-icon v-else @click="handleShowPwd" iconClass="暗文" class="el-input__icon el-icon-view" style="cursor: pointer;height: 32px;font-size: 12px;color: #C0C4CC;vertical-align: middle;margin-right: 6px;" /> </span ></span> </div> <div v-show="errorPwd" class="el-form-item__error"> 明码不能为空 </div> </div></template><script>/** * 手写明码,不反对右键菜单、复制、黏贴、剪切 */export default { name: 'handPassword', props: { // 输入框的id inputId: { type: String, default: 'passwordInput' }, // 后门:用户名称,不便开发应用浏览器记住明码 account: { type: String, default: '' }, // 须要应用子组件的校验,个别不应用 needValidatePwd: { type: Boolean, default: false }, // 输入框的暗正文 placeholder: { type: String, default: '请输出明码' }, // 输入框的最大输出长度 maxLength: { type: Number, default: 100 }, // 输入框头部图标类名 prefixIconName: { type: String, default: '' }, // 初始化明码值,个别用于编辑表单 originPwd: { type: String, default: '' } }, data() { return { secretPwd: '', //暗文明码 clearPwd: '', //明文明码 showPwd: false, //是否显示明文 errorPwd: false //是否明码谬误 } }, watch: { /** * 监听初始化明码,将明文和暗文明码别离初始化 */ originPwd: { handler(val) { this.clearPwd = val this.secretPwd = '●'.repeat(val.length) }, immediate: true } }, created() { /** * 禁止浏览器右键,因为右键菜单里有撤销、重写、黏贴、复制 */ window.oncontextmenu = function(e) { e.preventDefault() } }, methods: { /** * 重置办法,个别是给父组件调用 */ reset() { this.showPwd = false this.errorPwd = false }, /** * 查看明码 */ checkPassword() { if (this.needValidatePwd) { if (this.clearPwd === '') { this.errorPwd = true } else { this.errorPwd = false } } }, /** * 点击明码框后的小眼睛,切换明文或暗文 */ handleShowPwd() { if (this.showPwd) { this.secretPwd = '●'.repeat(this.secretPwd.length) } else { this.secretPwd = JSON.parse(JSON.stringify(this.clearPwd)) } this.showPwd = !this.showPwd }, /** * 输出明码 */ inputPassword(val) { const inputVal = val.target.value //原生input须要取target.value // 如果明文展现或者只输出了一个字符,比较简单,间接复制 if (this.showPwd || inputVal.indexOf('●') === -1) { if (this.showPwd) { this.secretPwd = inputVal } else { this.secretPwd = '●'.repeat(inputVal.length) } this.clearPwd = inputVal } else { const planeTextLen = this.clearPwd.length, //明文长度 cipherTextLen = inputVal.length, //暗文长度 selectionEnd = document.getElementById(this.inputId).selectionEnd // 获取光标地位 const realArr = this.clearPwd.split(''), // 实在明码数组 coverArr = inputVal.split('') // 文本框显示明码数组 let index = -1 // 新输出的字符地位 let lastChar = '' // 新输出的字符 // 找到新输出的字符及地位 coverArr.forEach((el, idx) => { if (/[^●]/g.test(el)) { index = idx lastChar += el } }) if (planeTextLen < cipherTextLen) { // 新增 realArr.splice(index, 0, lastChar) } else if (cipherTextLen <= planeTextLen && index !== -1) { //替换 realArr.splice(index, planeTextLen - (cipherTextLen - 1), lastChar) } else { // 删除 realArr.splice(selectionEnd, planeTextLen - cipherTextLen) } this.clearPwd = realArr.join('') this.secretPwd = '●'.repeat(this.secretPwd.length) // 还原光标地位 this.$nextTick(() => { document.getElementById(this.inputId).selectionEnd = selectionEnd }) } this.checkPassword() // 告知父组件明文明码 this.$emit('inputPwd', this.clearPwd) } }}</script>