vue3实现短信验证码组件

短信验证码

基础用法

vue 复制代码
<sms-code :before-click="handleBeforeCode" :on-success="handleSuccess" style="margin-left: 10px"></sms-code>
html 复制代码
<div style="width: 100%; display: flex; flex-wrap: nowrap; align-items: center">
    <el-input v-model="forms.smsCode" clearable placeholder="请输入验证码" maxlength="6" />
    <sms-code :before-click="handleBeforeCode" style="--btn-height: 30px;margin-left: 10px"></sms-code>
</div>
js 复制代码
// 场景一:发送验证码前需要验证表单字段
const handleBeforeCode = async () => {
    return new Promise((resolve, reject) => {
        formRef1.value.validateField(["phone"], async (valid, fields) => {
            if (valid) {
                // 发送短信接口参数
                let data = {
                    phone: forms.value.phone,
                    type: "2",
                };
                resolve(data);
            }
        });
    });
};
// 场景二:不需要验证表单直接发送
const handleBeforeCode = async () => {
    return {
        phone: forms.value.phone,
        type: "2",
    };
};
// 监听发送成功回调
const handleSuccess = (res) => {
    if (res && res.code == "0") {
        console.log("短信发送成功!");
    } else if (res && res.code != "0") {
        console.log("短信发送失败!");
    }
};
属性名 说明 类型 默认值 可选值
type 类型 string button text
time 倒计时时间 Number 60
isVertify 是否安全验证 boolean true
before-click 发送验证码前的回调函数 Function ---
on-success 发送成功的回调函数 Function ---
--style ---------------------- ---------- ------ ------
--btn-width 按钮宽度 - ---
--btn-height 按钮高度 - ---
--btn-bg-color 按钮背景颜色 - ---
--btn-text-color 按钮文字颜色 - ---

组件代码

创建组件时,在components目录下创建SmsCode文件夹,然后创建index.vue粘贴组件代码

  • 组件代码里包含了滑块安全验证组件,详细使用参考滑块安全验证组件

    <template>
    <slot name="sendBefore" v-if="$slots.sendBefore" />
    发送验证码
    复制代码
          <!-- 发送中 -->
          <slot v-if="$slots.sendActive && smsCodeFlag === 'sendActive'" name="sendActive" :second="second" />
          <div v-else-if="smsCodeFlag === 'sendActive'" class="sms-code disabled">{{ second }}s</div>
    
          <!-- 发送后 -->
          <div @click="getPhoneCode()" v-if="smsCodeFlag === 'sendAfter'">
              <slot v-if="$slots.sendAfter" name="sendAfter" />
              <div v-else class="sms-code">重新获取</div>
          </div>
    
          <el-dialog v-model="dialogVisible" title="" width="360" :append-to-body="true" destroy-on-close>
              <template #header="{ titleId, titleClass }" v-if="dialogVisible">
                  <div class="my-header">
                      <p :id="titleId" :class="titleClass">安全验证</p>
                  </div>
              </template>
              <by-slider-vertify :on-success="handleSuccess"></by-slider-vertify>
          </el-dialog>
      </div>
    </template> <script setup> /* @sendBefore 发送前 @sendActive 发送中 @sendAfter 发送后 */ import request from "@/utils/request"; import BySliderVertify from "@/components/securityVertify/index.vue";

    const emit = defineEmits(["onSuccess"]);
    const second = ref(0);
    const smsCodeFlag = ref("sendBefore");
    const dialogVisible = ref(false);
    const axiosData = ref({});
    const props = defineProps({
    // 倒计时时间
    time: {
    type: Number,
    default: 60,
    },
    // 发送前的回调函数
    beforeClick: {
    type: Function,
    default: () => {},
    },
    // 是否需要滑块验证
    isVertify: {
    type: Boolean,
    default: true,
    },
    // 按钮类型 默认为button 可选值 text
    type: {
    type: String,
    default: "button",
    },
    });
    // 发送短信验证码
    const sendSmsCode = () => {
    sendCode();
    request({
    url: "/api/getSmsCode",
    method: "post",
    data: axiosData.value,
    }).then((res) => {
    emit("onSuccess", res);
    });
    };
    // 处理按钮点击事件
    const getPhoneCode = async () => {
    const isbefore = await props.beforeClick();
    if (isbefore) {
    axiosData.value = isbefore;
    if (props.isVertify) {
    dialogVisible.value = true;
    } else {
    sendSmsCode();
    }
    }
    };

    // 倒计时
    const sendCode = () => {
    let num = props.time;
    second.value = num;

    复制代码
      smsCodeFlag.value = "sendActive";
      let t = setInterval(function () {
          num--;
          if (num === 0) {
              clearInterval(t);
              smsCodeFlag.value = "sendAfter";
          } else {
              second.value = num;
          }
      }, 1000);

    };

    // 处理滑块验证成功
    const handleSuccess = () => {
    dialogVisible.value = false;
    sendSmsCode();
    };
    </script>

    <style lang="scss" scoped> .sms-box { cursor: pointer; --btn-width: 116px; --btn-height: 36px; --btn-bg-color: var(--theme-color, #007eff); --btn-text-color: #ffffff; height: var(--btn-height); &.sms-box-text { --btn-text-color: var(--btn-bg-color); .sms-code { background: transparent; color: var(--btn-text-color, #000); } } }

    .sms-code {
    width: var(--btn-width);
    height: var(--btn-height);
    line-height: var(--btn-height);
    background: var(--btn-bg-color);
    border-radius: 5px;
    text-align: center;
    color: var(--btn-text-color);
    user-select: none;
    &.disabled {
    background: #909399;
    cursor: not-allowed;
    }
    &:active {
    transform: translate(1px, 1px);
    }

    复制代码
      &.disabled:active {
          transform: translate(0);
      }

    }
    </style>

相关推荐
极客密码2 小时前
感谢雷总!Mimo大模型价值¥659/月的 MAX 套餐,让我免费领到了!
前端·ai编程·claude
深念Y3 小时前
我明白为什么B站没法在浏览器开直播了——Windows Chrome推流踩坑全记录
前端·chrome·webrtc·浏览器·srs·直播·flv
zhangxingchao3 小时前
AI应用开发七:可以替代 RAG 的技术
前端·人工智能·后端
Sun@happy3 小时前
现代 Web 前端渗透——基础篇(1)
前端·web安全
希冀1234 小时前
【CSS学习第十一篇】
前端·css·学习
隔窗听雨眠4 小时前
doctype、charset、meta如何控制整个渲染流水线
java·服务器·前端
kyriewen4 小时前
写组件文档写到吐?我用AI自动生成Storybook,同事以后直接抄
前端·javascript·面试
excel4 小时前
🧠 Prisma 表名大写 vs SQL 导出小写问题深度解析(附踩坑与解决方案)
前端·后端
周淳APP4 小时前
【前端工程化原理通识:从源头到运行时的理论阐述】
前端·编译·打包·前端工程化
五点六六六5 小时前
你敢信这是非Native页面写出来的渐变效果吗🌝(底层原理解析
前端·javascript·面试