禁止浏览器自动填充账号密码

在element-plus项目下,某些输入框不需要自动填充账号密码。

1.方案

将el-input的readonly设置为一个变量,默认为true,就不会被填充了,监听click事件,当点击时readonly变量再设为false

<el-input
  v-model="payForm.pwd"
  type="password"
  placeholder="请输入密码"
  autocomplete="new-password"
  @click="handlePwdMouseenter"
  :readonly="inputReadonly"
  show-password
  clearable
/>


const inputReadonly = ref(true)
const handlePwdMouseenter = () => {
  inputReadonly.value = false
} 

2.vue快捷指令

将el-input的readonly变动方案写为vue指令,可以快捷调用

<el-input
  v-prevent-auto-fill
  v-model="payForm.pwd"
  type="password"
  placeholder="请输入密码"
  show-password
  clearable
/>

编写指令文件prevent-auto-fill.ts

import type { DirectiveBinding, ObjectDirective } from 'vue'

interface PreventAutoFillOptions {
  selector?: string // 自定义选择器
  delay?: number // 自定义延迟时间
}

/**
 * 防止浏览器自动填充密码的指令
 * @param el - 指令绑定的元素
 * @param binding - 指令绑定的值
 */
function preventAutoFillMounted (el: HTMLElement, binding: DirectiveBinding<PreventAutoFillOptions>): void {
  // 获取配置选项
  const options: PreventAutoFillOptions = binding.value || {}
  const selector = options.selector ?? '.el-input__inner'

  // 获取输入元素
  const inputElement = el.querySelector(selector) as HTMLInputElement

  if (!inputElement) {
    throw new Error('[preventAutoFill] 未找到目标输入元素')
  }

  // 初始设置为只读,防止自动填充
  inputElement.setAttribute('autocomplete', 'off')
  inputElement.readOnly = true

  /**
   * 处理输入事件,防止自动填充
   * @param event - 事件对象
   */
  function handleEvent (event: Event): void {
    const target = event.target as HTMLInputElement
    if (target.value === '') {
      inputElement.readOnly = true
      window.requestAnimationFrame(() => {
        inputElement.readOnly = false
      })
    }
  }

  // 绑定事件监听器
  inputElement.addEventListener('input', handleEvent)
  inputElement.addEventListener('mousedown', handleEvent)

  // 存储事件处理函数,以便在 unmounted 时移除
  ;(el as any)._preventAutoFillCleanup = () => {
    inputElement.removeEventListener('input', handleEvent)
    inputElement.removeEventListener('mousedown', handleEvent)
  }
}

/**
 * 指令卸载时清理事件监听器
 * @param el - 指令绑定的元素
 */
function preventAutoFillUnmounted (el: HTMLElement): void {
  if ((el as any)._preventAutoFillCleanup) {
    ;(el as any)._preventAutoFillCleanup()
    delete (el as any)._preventAutoFillCleanup
  }
}

/**
 * 防止浏览器自动填充密码的指令
 */
const preventAutoFill: ObjectDirective<HTMLElement, PreventAutoFillOptions> = {
  mounted: preventAutoFillMounted,
  unmounted: preventAutoFillUnmounted
}

export default preventAutoFill

禁止浏览器密码输入框弹出历史密码提示框

在浏览器下,密码输入框输入时会弹出历史密码提示框,在实现禁止填充密码后仍会弹出历史密码框

image.png

方案1:text-security: disc

将input类型设为text,设置input的样式text-security: disc;
text-security: disc; 是一个非标准的 CSS 属性,主要用于将文本内容显示为圆点(●),常用于模拟密码输入框的隐藏效果。

<el-form-item label="确认密码" prop="confirmPwd">
  <el-input :class="passwordType === 'text' ? 'pwd' : ''" type="text" autocomplete="new-password" placeholder="请再次输入密码" v-model="ruleForm.confirmPwd">
    <template #suffix>
      <el-icon v-if="ruleForm.confirmPwd" class="cursor-pointer mr-8px" @click="ruleForm.confirmPwd = ''"><CircleClose /></el-icon>
      <el-icon v-if="ruleForm.confirmPwd" class="cursor-pointer" @click="passwordType = passwordType === 'password' ? 'text' : 'password'">
        <View v-if="passwordType === 'password'" />
        <Hide v-else />
      </el-icon>
    </template>
  </el-input>
</el-form-item>

const passwordType = ref('text')

.pwd {
  text-security: disc;
  -webkit-text-security: disc;
}

效果如下:
image.png

缺点:
● text-security: disc有兼容性问题
● input类型设为text时可以输入中文密码
● 在火狐浏览器上text-security: disc与密码框(type="password")样式不一样(如上图,大小圆圈不一样)

方案2:监听input事件,阻止默认行为

利用input监听键盘输入和鼠标点击事件,阻止默认行为(防止浏览器打开历史账号记录)

<el-form-item label="密码" prop="password">
  <el-input
    v-model="ruleForm.pwd"
    type="password"
    auto-complete="new-password"
    ref="newPwdRef"
    @keypress="handleKeypress"
    @keydown="handleKeydown"
    @mousedown="handleMousedown"
    show-password
    clearable
  ></el-input>
</el-form-item>

const newPwdRef = ref()
const handleKeypress = (evt) => {
  evt.stopPropagation()
  evt.preventDefault()
  const newPwd = ruleForm.pwd + evt.key
  // 过滤掉中文和空格
  ruleForm.pwd = newPwd.replace(/[u4e00-u9fa5s]/g, '')
}
// 监听按键按下(推荐用 keydown)
const handleKeydown = (e) => {
  if (e.key === 'Backspace') {
    e.preventDefault()
    ruleForm.pwd = ruleForm.pwd.slice(0, -1)
  }
}

const handleMousedown = (e) => {
  e.preventDefault()
  const inputElement = newPwdRef.value.$el.querySelector('input')
  setTimeout(() => {
    inputElement.focus()
  }, 0)
  
  if (inputElement) {
    function yourHandler () {
      inputElement.blur()
      setTimeout(() => {
        inputElement.focus()
        inputElement.removeEventListener('mousedown', yourHandler)
      }, 0)
    }
    inputElement.addEventListener('mousedown', yourHandler)
  }
}

缺点:
● 鼠标无法选择输入的密码,Ctrl+a全选不能删除
● 输入中文不会自动清空

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]