前端实现禁止浏览器记住密码功能

2,117 阅读1分钟

在网上搜了很多的解决方案,基本上都没有完美解决的,而完美解决就是在浏览器设置中禁止记住密码(ps:小菜鸟的内心想法),项目的需求非得实现页面不记住密码的功能,只能硬着头皮实现了。

  1. autocomplete="off" 现代浏览器已经不支持,所以直接放弃了对密码框设置,直接使用 autocomplete="new-password" ,亲测Chrome(v88.0.4324.104)、edge(v88.0.705.56)及火狐(v67)可用,但火狐(v85)还是会提示记住密码。参考:关闭表单自动填充
  2. 使用 type="text",手动替换文本框内容小圆点 “●”。(没有用星号 “”做替换是因为用户输入“”的话,没办法处理 )

最终选择用type='text',并手动替换内容。

先看效果: 动画.gif 基本上实现了el-input密码框的功能。

template

<template>
  <el-input
    v-model="showValue"
    type="text"
    v-bind="$attrs"
    @input.native="handleChangePSW($event)"
  />
</template>

script

<script>
export default {
  name: 'Password',
  props: {
    value: {
      type: String,
      default: ''
    },
    type: {
      type: String,
      default: 'password'
    }
  },
  data() {
    return {
      password: '', // 真实密码
      showValue: '', // 显示字符
      replaceChar: '•' // ●ꔷ•᛫・
    }
  },
  computed: {
  },
  watch: {
    type(value) {
      if (value === 'password') {
        this.showValue = this.replaceChar.repeat(this.value.length)
      } else {
        this.showValue = this.value
      }
    }
  },
  methods: {
    handleChangePSW(e) {
      console.log(e, 'e')
      const value = e.target.value // 当前的值
      if (!value) {
        this.password = ''
        this.showValue = ''
      } else {
        // 只能输入大小写字母、数字、字符
        const reg = /^[\w|~`!@#$%^&*()_-+=<>?:"{}\;',./:"<>?[]|·~!¥……()——【】、;‘’,。、:“”《》?•]+$/g
        if (!reg.test(value)) {
          // e.target.value = value.replace(/[\u4e00-\u9fa5]/gm, '')
          e.target.value = this.showValue // 将之前未包含中文的值,重新赋值
          return
        }
​
        if (this.type === 'password') {
          const oldVal = this.password // 之前的值
          let passwordShow = '' // 当前输入下需要显示的值,及n个*的字符串
          let text = '' // 当前input事件输入的值,如果是删除就没有值
          // 当前input指针的位置,不一定是在最后
          const startPoint = e.target.selectionStart
          const endPoint = e.target.selectionEnd
​
          let leftNum = 0 // 输入后左边保留多少
          let rightNum = 0 // 输入后右边保留多少
          let isLeft = true
          for (let i = 0; i < value.length; i++) {
            passwordShow += this.replaceChar
            if (value[i] === this.replaceChar) { // ●ꔷ•᛫・
              if (isLeft) {
                leftNum++
              } else {
                rightNum++
              }
              continue
            }
            text += value[i]
            isLeft = false
          }
​
          if (text) {
            this.password = oldVal.slice(0, leftNum) + text + oldVal.slice(oldVal.length - rightNum)
          } else {
            if (startPoint >= value.length) {
              this.password = oldVal.slice(0, startPoint) + oldVal.slice(oldVal.length - leftNum - rightNum + startPoint)
            } else {
              this.password = oldVal.slice(0, startPoint) + oldVal.slice(oldVal.length - leftNum - rightNum + endPoint)
            }
          }
          this.showValue = passwordShow
          this.$nextTick(() => {
            e.target.setSelectionRange(startPoint, startPoint)
          })
        } else {
          this.password = this.showValue = value
        }
      }
​
      this.$emit('input', this.password)
    }
  }
}
</script>

上面的代码是封装成一个组件的代码,只需要在父组件中引用,就可以实现模拟密码框的功能,基本上实现了替换功能、限制中文的输入、密码的查看;下图就是在父组件的引用代码。

image.png 0C751DA6-36A1-449f-BEA9-49788A8CC134.png 图中红色框就是el-input的type='password'的功能代码,绿色框中的代码就是模仿实现。