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>

相关推荐
chenbin___1 天前
JavaScript 中!!、?? 和 || 使用介绍
前端·javascript·vue.js
chilavert3181 天前
技术演进中的开发沉思-279 AJax :Rich Text Editor(下)
前端·javascript·ajax
玄同7651 天前
面向对象编程 vs 其他编程范式:LLM 开发该选哪种?
大数据·开发语言·前端·人工智能·python·自然语言处理·知识图谱
天呐草莓1 天前
部署 Vue 项目到阿里云云服务器
服务器·前端·vue.js
初遇你时动了情1 天前
不用每个请求都写获取请求 类似无感刷新逻辑 uniapp vue3 react实现方案
javascript·react.js·uni-app
海阔天空091 天前
Cesium三维地形渲染
vue.js·github
27669582921 天前
京东最新滑块 分析
linux·前端·javascript·h5st·京东滑块·京东m端滑块·京东逆向
加洛斯1 天前
Pinia入门指南:三步上手,搞定状态管理
前端·vue.js