Vue表单输入密码实现密码格式和强度验证提示框-demo

发布时间:2024年01月18日

实现效果

实现过程

校验

//密码格式校验
const validateUppercase = (rule, value, callback) => {
  if (!/[A-Z]/.test(value)) {
    callback(new Error('密码必须包含至少一个大写字母'));
  } else {
    callback();
  }
};
const validateNumber = (rule, value, callback) => {
  if (!/\d/.test(value)) {
    callback(new Error('密码必须包含至少一个数字'));
  } else {
    callback();
  }
};
const validateSpecialCharacter = (rule, value, callback) => {
  if (!/[~`!@#$%^&*()_\-+={}[\]|;:,<>.?/]/.test(value)) {
    callback(new Error('密码必须包含至少一个特殊字符'));
  } else {
    callback();
  }
};

源代码?

<template>
  <div class="registerform">
    <h1>注册账户</h1>
    <div class="registerWarp">
      <el-form
        label-position="top"
        label-width="100px"
        :model="form"
        ref="ruleFormRef"
        :rules="rulesForm"
        hide-required-asterisk
        class="register-form"
      >
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="form.email" placeholder="电子邮箱" />
        </el-form-item>
        <el-form-item label="密码" prop="pwd">
          <el-input
            v-model="form.pwd"
            type="password"
            show-password
            placeholder="登录密码"
            @focus="showTooltip"
            @blur="hideTooltip"
            @input="handleInput"
          />
        <!-tips提示->
          <div class="pwdTips" v-show="isPwdShowTips">
            <p>
              <img
                v-show="!isCheck1"
                src="@/assets/images/register/check-0.svg"
              />
              <img
                v-show="isCheck1"
                src="@/assets/images/register/check-1.svg"
              />
              <span>6-24个字符</span>
            </p>
            <p>
              <img
                v-show="!isCheck2"
                src="@/assets/images/register/check-0.svg"
              />
              <img
                v-show="isCheck2"
                src="@/assets/images/register/check-1.svg"
              />
              <span>至少一个大写字母</span>
            </p>
            <p>
              <img
                v-show="!isCheck3"
                src="@/assets/images/register/check-0.svg"
              />
              <img
                v-show="isCheck3"
                src="@/assets/images/register/check-1.svg"
              />
              <span>至少一个数字</span>
            </p>
            <p>
              <img
                v-show="!isCheck4"
                src="@/assets/images/register/check-0.svg"
              />
              <img
                v-show="isCheck4"
                src="@/assets/images/register/check-1.svg"
              />
              <span>至少一个特殊字符</span>
            </p>
            <p>特殊字符支持:~`!@#$%^&amp;*()_-+={}[]|;:,&lt;&gt;.?/</p>
          </div>
        </el-form-item>
        <el-form-item>
          <template #label>
            <div class="item-label">
              <span>填写邀请ID(选填)</span>
              <img
                :class="{ active: isIdShow }"
                @click="isIdShow = !isIdShow"
                src="@/assets/images/register/right-jian.svg"
              />
            </div>
          </template>
          <el-input
            v-show="isIdShow"
            v-model="form.parentShortId"
            placeholder="填写邀请用户ID"
          />
        </el-form-item>
        <el-form-item>
          <div class="form-bottom">
            <div class="promise">
              点击注册即表示同意<span>服务协议</span>和<span>隐私条款</span>
            </div>
            <div
              class="submit-btn"
              type="primary"
              @click="submitForm(ruleFormRef)"
            >
              注册
            </div>
            <div class="switch-login">
              已有账户?<span @click="goPath('/login')">去登录</span>
            </div>
          </div>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, defineEmits, watch } from 'vue';
import { emailCodeSend } from '@/api/user';
import { EmailSceneTypeMap } from '@/views/Login/const.js';
import { debounce } from '@/utils';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
const router = useRouter();
const store = useStore();

const goPath = (r) => {
  router.push({
    path: r
  });
};
const isIdShow = ref(false);
const ruleFormRef = ref(null);
const form = reactive({
  email: '',
  pwd: '',
  code: '',
  parentShortId: '',
  captcha: '123456'
});

// 发送验证码
const getEmailCode = debounce(async (val) => {
  try {
    await store.dispatch('app/showLoading');
    let params = {
      scene: EmailSceneTypeMap['REGISTER'],
      email: val,
      captcha: '123456'
    };
    const { data } = await emailCodeSend(params);
    console.log(data);
    if (data.code == 'Success') {
      store.dispatch(
        'app/showToast',
        {
          msg: '验证码已发送',
          type: 'success'
        },
        { root: true }
      );
      emits('stepRouter', { step: 2, form });
      return data.data.sec;
    }
  } catch (error) {
    console.log('getEmailCode-Error', error);
  } finally {
    await store.dispatch('app/hideLoading');
  }
}, 300);

// 密码提示
const isPwdShowTips = ref(false);
const showTooltip = () => {
  console.log('showTooltip');
  isPwdShowTips.value = true;
  handleInput(form.pwd);
};

const hideTooltip = () => {
  console.log('hideTooltip');
  isPwdShowTips.value = false;
};

// 输入框校验
const isCheck1 = ref(false);
const isCheck2 = ref(false);
const isCheck3 = ref(false);
const isCheck4 = ref(false);
const handleInput = (value) => {
  console.log('handleInput');
  if (value.length < 6 || value.length > 24) {
    isCheck1.value = false;
  } else {
    isCheck1.value = true;
  }
  if (!/[A-Z]/.test(value)) {
    isCheck2.value = false;
  } else {
    isCheck2.value = true;
  }
  if (!/\d/.test(value)) {
    isCheck3.value = false;
  } else {
    isCheck3.value = true;
  }
  if (!/[~`!@#$%^&*()_\-+={}[\]|;:,<>.?/]/.test(value)) {
    isCheck4.value = false;
  } else {
    isCheck4.value = true;
  }
};

//密码格式校验
const validateUppercase = (rule, value, callback) => {
  if (!/[A-Z]/.test(value)) {
    callback(new Error('密码必须包含至少一个大写字母'));
  } else {
    callback();
  }
};
const validateNumber = (rule, value, callback) => {
  if (!/\d/.test(value)) {
    callback(new Error('密码必须包含至少一个数字'));
  } else {
    callback();
  }
};
const validateSpecialCharacter = (rule, value, callback) => {
  if (!/[~`!@#$%^&*()_\-+={}[\]|;:,<>.?/]/.test(value)) {
    callback(new Error('密码必须包含至少一个特殊字符'));
  } else {
    callback();
  }
};
const rulesForm = reactive({
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { type: 'email', message: '邮箱输入格式错误', trigger: 'blur' }
  ],
  pwd: [
    { required: true, message: '请输入密码', trigger: 'blur' },
    { min: 6, max: 24, message: '密码长度为6-24个字符', trigger: 'blur' },
    { validator: validateUppercase, trigger: 'blur' },
    { validator: validateNumber, trigger: 'blur' },
    { validator: validateSpecialCharacter, trigger: 'blur' }
  ]
});

const emits = defineEmits(['stepRouter']);

const submitForm = (formEl) => {
  if (!formEl) return;
  formEl.validate((valid) => {
    if (valid) {
      console.log('submit!');
      getEmailCode(form.email);
      // emits('stepRouter', { step: 2, form });
    } else {
      console.log('error submit!');
      return false;
    }
  });
};
</script>

<style lang="less" scoped>
.registerform {
  h1 {
    color: #000;
    font-family: PingFang SC;
    font-size: 40px;
    font-style: normal;
    font-weight: 600;
    line-height: normal;
    margin-bottom: 40px;
  }
  .registerWarp {
    .register-form {
//提示
      .pwdTips {
        position: absolute;
        top: 51px;
        width: 480px;
        min-height: 210px;
        flex-shrink: 0;
        background-color: #fff;
        z-index: 1;
        border-radius: 5px;
        box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.15);
        padding: 20px;
        p {
          display: flex;
          align-items: center;
          color: #000;
          font-family: PingFang SC;
          font-size: 14px;
          font-weight: 400;
          padding-bottom: 10px;

          img {
            margin-right: 11px;
          }
          &:last-child {
            color: #909090;
            font-family: PingFang SC;
            font-size: 12px;
            font-weight: 500;
            padding-bottom: 0;
          }
        }
      }
      &.el-form {
        :deep(.el-form-item__label) {
          color: #000;
          font-family: PingFang SC;
          font-size: 14px;
          font-style: normal;
          font-weight: 400;
          line-height: normal;
          margin-bottom: 0;
        }
        .el-form-item {
          position: relative;
          margin-top: 20px;
          .form-bottom {
            .promise {
              color: #000;
              font-family: PingFang SC;
              font-size: 14px;
              font-style: normal;
              font-weight: 400;
              line-height: normal;
              span {
                color: #3183ff;
              }
            }
            .submit-btn {
              width: 480px;
              height: 48px;
              border-radius: 40px;
              background: #090909;
              color: #fff;
              font-family: PingFang SC;
              font-size: 14px;
              font-style: normal;
              font-weight: 400;
              line-height: normal;
              display: flex;
              justify-content: center;
              align-items: center;
              margin-top: 20px;
              margin-bottom: 30px;
              user-select: none;
              cursor: pointer;
            }
            .switch-login {
              color: #000;
              font-family: PingFang SC;
              font-size: 14px;
              font-style: normal;
              font-weight: 400;
              line-height: normal;
              text-align: center;
              span {
                color: #3183ff;
                cursor: pointer;
              }
            }
          }
          .item-label {
            display: flex;
            justify-content: space-between;
            img {
              width: 11px;
              height: 11px;
              transform: rotate(90deg);
              transition: transform 0.3s ease;
              cursor: pointer;
              &.active {
                transform: rotate(270deg);
              }
            }
          }
          .el-input {
            width: 480px;
            height: 40px;
            background: #ffffff;
            margin-top: 10px;
            border: 1px solid #ebebeb;
            border-radius: 4px;
            ::placeholder {
              font-size: 14px;
              line-height: 20px;
              color: #c8c8c8;
            }
          }
          :deep(.el-input__inner) {
            color: #000;
          }
        }
      }
    }
  }
}
</style>
文章来源:https://blog.csdn.net/JackieDYH/article/details/132805369
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。