index.vue 1.88 KB
<template>
  <div>
    <ElInput
      type="password"
      :value="value"
      :placeholder="placeholder"
      :clearable="clearable"
      autocomplete="new-password"
      @input="$emit('input', arguments[0])"
    >
      <div
        slot="suffix"
        title="密码强度"
        class="password-strength"
      >
        <div
          class="password-strength--fill"
          :data-score="passwordStrength"
        />
      </div>
    </ElInput>
  </div>
</template>

<script>
import zxcvbn from 'zxcvbn'

export default {
  props: {
    value: {
      type: String,
      default: null
    },
    placeholder: {
      type: String,
      default: null
    },
    clearable: {
      type: Boolean
    }
  },
  computed: {
    passwordStrength() {
      return this.value ? zxcvbn(this.value).score : 0
    }
  }
}
</script>

<style scoped>
.password-strength {
  vertical-align: text-bottom;
  position: relative;
  display: inline-block;
  width: 25px;
  height: 15px;
  border-bottom: 15px solid #dcdfe6;
  border-left: 25px solid transparent;
}

.password-strength--fill {
  position: absolute;
  left: -25px;
  bottom: -15px;
  display: inline-block;
  border-bottom: 15px solid #dcdfe6;
  border-left: 25px solid transparent;
  transition: border 0.5s ease-in-out, background 0.25s;
}

.password-strength--fill[data-score='0'] {
  border-bottom: 3px solid darkred;
  border-left: 5px solid transparent;
}

.password-strength--fill[data-score='1'] {
  border-bottom: 6px solid orangered;
  border-left: 10px solid transparent;
}

.password-strength--fill[data-score='2'] {
  border-bottom: 9px solid orange;
  border-left: 15px solid transparent;
}

.password-strength--fill[data-score='3'] {
  border-bottom: 12px solid yellowgreen;
  border-left: 20px solid transparent;
}

.password-strength--fill[data-score='4'] {
  border-bottom: 15px solid green;
  border-left: 25px solid transparent;
}
</style>