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>

相关推荐
浩星5 小时前
css实现类似element官网的磨砂屏幕效果
前端·javascript·css
一只小风华~5 小时前
Vue.js 核心知识点全面解析
前端·javascript·vue.js
2022.11.7始学前端5 小时前
n8n第七节 只提醒重要的待办
前端·javascript·ui·n8n
SakuraOnTheWay5 小时前
React Grab实践 | 记一次与Cursor的有趣对话
前端·cursor
阿星AI工作室5 小时前
gemini3手势互动圣诞树保姆级教程来了!附提示词
前端·人工智能
徐小夕5 小时前
知识库创业复盘:从闭源到开源,这3个教训价值百万
前端·javascript·github
xhxxx5 小时前
函数执行完就销毁?那闭包里的变量凭什么活下来!—— 深入 JS 内存模型
前端·javascript·ecmascript 6
StarkCoder6 小时前
求求你试试 DiffableDataSource!别再手算 indexPath 了(否则迟早崩)
前端
fxshy6 小时前
Cursor 前端Global Cursor Rules
前端·cursor
红彤彤6 小时前
前端接入sse(EventSource)(@fortaine/fetch-event-source)
前端