关于前端:Vue组件禁止浏览器记住密码-自动填写密码

10次阅读

共计 4344 个字符,预计需要花费 11 分钟才能阅读完成。

禁止浏览器记住明码、主动填写明码,反对明文暗文显示明码

应用办法:父组件中引入 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>
正文完
 0