微信小程序 == 倒计时验证码组件 (countdown-verify)

组件介绍

这是一个用于获取验证码的倒计时按钮组件,支持自定义倒计时时间、按钮样式和文字格式。

基本用法

javascript 复制代码
<countdown-verify 
  seconds="60"
  button-text="获取验证码"
  bind:send="onSendVerifyCode"
/>

属性说明

属性名 类型 默认值 说明
seconds Number 60 倒计时总时长(秒),必须大于0
buttonText String "获取验证码" 按钮默认显示的文字
countdownFormat String "剩余%s秒" 倒计时过程中显示的文字格式,%s会被替换为剩余秒数
buttonStyle String "" 按钮的样式,支持内联样式
disabledStyle String "background-color: #cccccc; color: #ffffff;" 倒计时过程中按钮的样式
instanceId String "" 组件实例ID,用于多实例区分,不传会自动生成

事件说明

事件名 说明 参数
send 点击获取验证码按钮时触发 { instanceId: string }
start 倒计时开始时触发 { instanceId: string }
end 倒计时结束时触发 { instanceId: string }

方法说明

方法名 说明 参数 返回值
start() 开始倒计时
stop() 停止倒计时
reset() 重置倒计时
getStatus() 获取当前状态 { isCounting: boolean, remaining: number, instanceId: string }

使用示例

javascript 复制代码
Page({
  data: {
    // ...
  },
  
  onSendVerifyCode(e) {
    // 发送验证码请求
    wx.request({
      url: 'your-api-url',
      success: () => {
        // 请求成功后开始倒计时
        this.selectComponent('#verifyCode').start();
      }
    });
  }
});

注意事项

组件会自动处理倒计时过程中的状态切换

倒计时过程中按钮会被禁用

组件销毁时会自动清理定时器

支持多个实例同时使用,每个实例都有唯一的instanceId

倒计时时间必须大于0,否则会自动设置为60秒

样式定制

可以通过 buttonStyle 和 disabledStyle 属性来自定义按钮样式,支持所有CSS属性。

javascript 复制代码
<countdown-verify 
  button-style="background-color: #007AFF; color: white; border-radius: 4px;"
  disabled-style="background-color: #999999; color: white;"
/>

完整代码

js

javascript 复制代码
// components/countdown-verify/countdown-verify.js
Component({
  properties: {
    // 倒计时总时长(秒)
    seconds: {
      type: Number,
      value: 60,
      observer: function (newVal) {
        if (newVal <= 0) {
          console.warn("倒计时时间必须大于0");
          this.setData({ seconds: 60 });
        }
      },
    },
    // 按钮默认文字
    buttonText: {
      type: String,
      value: "获取验证码",
    },
    // 禁用状态下的文字格式
    countdownFormat: {
      type: String,
      value: "剩余%s秒",
    },
    // 按钮样式
    buttonStyle: {
      type: String,
      value: "",
    },
    // 禁用状态按钮样式
    disabledStyle: {
      type: String,
      value: "background-color: #cccccc; color: #ffffff;",
    },
    // 实例ID,用于多实例区分
    instanceId: {
      type: String,
      value: "",
    },
  },

  data: {
    remaining: 0,
    isCounting: false,
    timer: null,
    displayText: "",
  },

  lifetimes: {
    attached() {
      // 生成唯一实例ID
      if (!this.properties.instanceId) {
        this.setData({
          instanceId:
            "countdown_" +
            Date.now() +
            "_" +
            Math.random().toString(36).substr(2),
        });
      }
      this.updateDisplayText();
    },
    detached() {
      this.clearTimer();
    },
  },
  // 监听倒计时和是否正在倒计时,更新显示文本
  observers: {
    "remaining, isCounting": function (remaining, isCounting) {
      this.updateDisplayText();
    },
  },

  methods: {
    // 更新显示文本
    updateDisplayText() {
      const text = this.data.isCounting
        ? this.properties.countdownFormat.replace("%s", this.data.remaining)
        : this.properties.buttonText;
      this.setData({ displayText: text });
    },

    // 开始倒计时
    start() {
      if (this.data.isCounting) {
        console.warn("倒计时正在进行中");
        return;
      }

      this.clearTimer();

      this.setData({
        isCounting: true,
        remaining: this.properties.seconds,
      });

      this.data.timer = setInterval(() => {
        const remaining = this.data.remaining - 1;
        if (remaining <= 0) {
          this.stop();
          return;
        }
        this.setData({ remaining });
      }, 1000);

      this.triggerEvent("start", { instanceId: this.data.instanceId });
    },

    // 停止倒计时
    stop() {
      this.clearTimer();
      this.setData({
        isCounting: false,
        remaining: 0,
      });
      this.triggerEvent("end", { instanceId: this.data.instanceId });
    },

    // 清除定时器
    clearTimer() {
      if (this.data.timer) {
        clearInterval(this.data.timer);
        this.data.timer = null;
      }
    },

    // 按钮点击事件
    handleTap() {
      if (!this.data.isCounting) {
        this.triggerEvent("send", { instanceId: this.data.instanceId });
      }
    },

    // 重置倒计时
    reset() {
      this.stop();
    },

    // 获取当前状态
    getStatus() {
      return {
        isCounting: this.data.isCounting,
        remaining: this.data.remaining,
        instanceId: this.data.instanceId,
      };
    },
  },
});

wxml

xml 复制代码
<!-- components/countdown-verify/countdown-verify.wxml -->
<button style="{{isCounting ? disabledStyle : buttonStyle}}" disabled="{{isCounting}}" bind:tap="handleTap" aria-label="{{isCounting ? '倒计时中' : buttonText}}" data-instance-id="{{instanceId}}">
    {{displayText}}
</button>

wxss

xml 复制代码
/* components/countdown-verify/countdown-verify.wxss */
button {
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  font-size: 28rpx;
  line-height: 1.5;
  text-align: center;
  border-radius: 8rpx;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  min-width: 180rpx;
  height: 80rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

button[disabled] {
  opacity: 0.6;
}
button::after {
  border: none;
}

json

xml 复制代码
{
  "component": true,
  "usingComponents": {}
}
相关推荐
全职计算机毕业设计6 小时前
基于微信小程序的城市特色旅游推荐应用的设计与实现
微信小程序·小程序
gaojianqiao123410 小时前
uniapp引入七鱼客服微信小程序SDK
微信小程序·uni-app
说私域11 小时前
线下消费经济“举步维艰”,开源AI智能名片链动2+1+S2B2C小程序线上“狂飙突进”!
人工智能·小程序·开源·零售
天上掉下来个程小白13 小时前
添加购物车-02.代码开发
java·服务器·前端·后端·spring·微信小程序·苍穹外卖
JAVA叶知秋1 天前
uniapp自定义底部导航栏h5有效果小程序无效的解决方案
小程序·uni-app
沙尘暴炒饭2 天前
用uniapp在微信小程序实现画板(电子签名)功能,使用canvas实现功能
微信小程序·小程序·uni-app
PyAIGCMaster2 天前
Taro 编译不平不同平台小程序
小程序
fakaifa2 天前
【开源版】likeshop上门家政系统PHP版全开源+uniapp前端
小程序·uni-app·php·家政小程序源码·家政服务小程序·源码下载·上门家政
说私域2 天前
基于定制开发开源AI智能名片S2B2C商城小程序的公私域流量融合运营策略研究
人工智能·小程序·开源·零售
阿諪諪2 天前
uniapp小程序中实现无缝衔接滚动效果
小程序·uni-app