首页 > 编程语言 >封装小程序倒计时组件

封装小程序倒计时组件

时间:2023-04-20 19:13:18浏览次数:42  
标签:count countdown 封装 wrapper 倒计时 var props 组件 main

适用范围:支付宝,淘宝小程序

效果:

 组件目录结构:

详情:
 index.axml

<!-- [{"value":["3","5"],"style":"","isTime":true},{"value":"秒","style":""}] -->
<view class="countdown-main-wrapper">
    <block a:for="{{parsedTime}}">
      <view style="{{item.style}}">
        <block a:if="{{item && item.value && item.value[0]}}">
          <!-- render time, eg. {"value":["3","5"],"style":"","isTime":true} -->
          <block a:if="{{item.isTime}}" >
            <block a:for="{{item.value}}" a:for-item="time" a:for-index="idx">
              <!-- set style for second -->
              <text a:if="{{idx == item.value.length - 1 && index == parsedTime.length - 2}}" style="{{secondStyle || timeStyle}}">{{time}}</text>
              <text a:else style="{{timeStyle}}">{{time}}</text>
            </block>
          </block>
          <!-- render text, eg, {"value":"秒","style":""} -->
          <text a:else style="{{textStyle}}" class="rax-countdown-main-wrapper-colon">{{item.value[0]}}</text>
        </block>
      </view>
    </block>
</view>

index.acss

.countdown-main-wrapper {
  display: flex;
  flex-direction: row;
  align-items: center;
}

.countdown-main-wrapper view:nth-child(2n-1)::after{ //冒号样式
  display:flex;
  justify-content: center;
  align-items: center;
  content:':';
  color:#3A3A3A;
  font-size:16rpx;
  font-family: PingFangSC-Medium;
  margin-top: -2rpx;
}

.countdown-main-wrapper view:nth-child(2n){ // 数字样式
  font-size:16rpx;
  color:#3A3A3A;
  font-family: PingFangSC-Medium;
  border-radius:3rpx;
  padding:0;
  background-color: transparent;
}

.countdown-main-wrapper view:nth-child(1)::after{
  content: '';
}

.countdown-main-wrapper view:last-child::after{
  content: '';
}

index.js

"use strict";

var _utils = require("./utils");

Component({
  data: {
    count: 0
  },
  props: {
    timeRemaining: 0,
    interval: 1000,
    timeWrapStyle: '',
    textStyle: '',
    timeStyle: '',
    secondStyle: '',
    tpl: '{d}天{h}时{m}分{s}秒',
    onFormatFunc: null,
    onTick: null,
    onComplete: null
  },
  onInit: function () {
    this.setTimes();
  },
  didUnmount: function () {
    if (this.counter) clearInterval(this.counter);
  },
  methods: {
    setTimes() {
      var _this = this;
      var funcToExecute = this.props.onFormatFunc && typeof this.props.onFormatFunc === 'function' ? this.props.onFormatFunc : this.msToTime;
      this.funcToExecute = funcToExecute.bind(this);
      this.counter = setInterval(function () {
        _this.funcToExecute();
      }, this.props.interval);
    },
    msToTime: function msToTime() {
      var _this2 = this;

      var count = this.data.count;
      var timeDuration = (this.data.leftTime || this.props.timeRemaining) - count * this.props.interval;
      this.setData({
        count: count + 1
      });

      if (!timeDuration || timeDuration <= 0) {
        if (this.counter) clearInterval(this.counter);
      } // parameter type of `parseInt` is 'string', so need to convert time to string first.

      let days = parseInt((timeDuration / (1000 * 60 * 60 * 24)).toString());

      const oneSeconds = 1000;
      const oneMinutes = oneSeconds * 60;
      const oneHours = oneMinutes * 60;

      // 计算相差小时数
      let hours = Math.floor(timeDuration / oneHours);
      // 计算相差分钟数
      let minutes = Math.floor((timeDuration % oneHours) / oneMinutes);
      // 计算相差秒数
      let seconds = Math.floor((timeDuration % oneMinutes) / oneSeconds);

      var timeType = {
        'd': days < 10 ? '0' + days : days + '',
        'h': hours < 10 ? '0' + hours : hours + '',
        'm': minutes < 10 ? '0' + minutes : minutes + '',
        's': seconds < 10 ? '0' + seconds : seconds + ''
      }; // format time

      var tpl = this.props.tpl || _utils.DEFAULT_TPL;
      var rule = new RegExp('\{[d,h,m,s]\}', 'g'); // used to matched all template item, which includes 'd', 'h', 'm' and 's'.

      var matchlist = [];
      var tmp = null;
      var _this$props = this.props,
        textStyle = _this$props.textStyle,
        timeWrapStyle = _this$props.timeWrapStyle;

      while ((tmp = rule.exec(tpl)) !== null) {
        matchlist.push(tmp.index, tmp.index);
      }

      if (matchlist.length !== 0) {
        // used to detect the last element
        matchlist.push(-1);
      }

      var lastPlaintextIndex = 0;
      var parsedTime = matchlist.map(function (val, index) {
        if (val === -1) {
          // don't forget the potential plain text after last matched item
          var lastPlaintext = tpl.slice(lastPlaintextIndex);
          return {
            value: lastPlaintext,
            style: textStyle
          };
        }

        var matchedCharacter = tpl[val + 1];

        switch (matchedCharacter) {
          case 'd':
          case 'h':
          case 'm':
          case 's':
            if (index % 2 === 0) {
              // insert plain text before current matched item
              return {
                value: tpl.slice(lastPlaintextIndex, val),
                style: textStyle
              };
            } else {
              // replace current matched item to realtime string
              lastPlaintextIndex = val + 3;
              return {
                value: _this2.splitTime(timeType[matchedCharacter]),
                style: timeWrapStyle,
                isTime: true
              };
            }

          default:
            return null;
        }
      });
      parsedTime = parsedTime.filter(function (item) {
        return item;
      }); // check if the onTick function needs to be called

      var callOnTick = this.props.onTick && typeof this.props.onTick === 'function';
      this.setData({
        parsedTime: parsedTime
      }, callOnTick ? this.props.onTick : null); // check if onComplete function needs to be called
      if (timeDuration <= 0 && this.props.onComplete && typeof this.props.onComplete === 'function') {
        this.props.onComplete();
      }
    },
    splitTime: function splitTime(time) {
      if (time === void 0) {
        time = '00';
      }

      return time.split('');
    }
  }
});

index.json

{
    "component": true
}

utils.js

"use strict";

exports.__esModule = true;
exports.DEFAULT_TPL = void 0;
var DEFAULT_TPL = '{d}天{h}时{m}分{s}秒';
exports.DEFAULT_TPL = DEFAULT_TPL;

 

用法:

 <count-down timeRemaining="{{123456}}"   tpl='{h}{m}{s}' />

 

 

标签:count,countdown,封装,wrapper,倒计时,var,props,组件,main
From: https://www.cnblogs.com/yujiawen/p/17337993.html

相关文章

  • Vue3 日历组件的实现
    Vue3日历组件的实现以下是一个基于Vue3实现的简单日历组件的代码示例。这个日历组件包含了前一个月、当前月、下一个月的日期,并且可以支持选择日期、切换月份等功能。<template><divclass="calendar"><divclass="header"><buttonclass="prev"@click="pre......
  • SpringBoot应用集成微服务组件Nacos
    目录springboot与微服务组件nacosNacos服务快速启动STS4开发工具Maven环境配置STS4开发工具引入Maven配置MavenRepo配置阿里云镜像源Springboot集成nacos服务springboot项目构建springboot集成微服务nacosnacos版本问题nacos2.0.0版本兼容性说明nacos升级文档nacos版本与spring......
  • 关于项目组件打包时遇到 `Uncaught TypeError: Cannot read property 'toLowerCase' o
    在全局注册组件时采用遍历组件池的方法时 每个组件都应该具备name属性 否则会出现UncaughtTypeError:Cannotreadproperty'toLowerCase'ofundefined  ......
  • 使用Layui树形组件如何取值
    近期使用了Layui中的树形组件来权限,发现无法没有提供直接获取选中值的id或code方法。分享一下个人方法官方案例 可以使用tree.getChecked('demoId')获取选中的节点,选中节点是个JSON无法直接获取指定code或者id等信息,需要我们自己处理一下 本方法可以获取指定层级的id或......
  • Vue独立组件开发: prop event slot
    本文是介绍独立组件开发的系列文章的第一篇。Vuejs无疑是当下最火热的前端框架,而它最精髓的,正是它的组件与组件化。写一个Vue项目,就是在写一个个的组件,掌握了Vue组件的各种开发模式与技巧,再复杂的业务场景也可轻松拿捏。组件的分类Vue组件分成三类:页面组件由 vue-router 产......
  • Vue 独立组件开发:不一样的组件通信方式
    本文是介绍独立组件开发的系列文章的第二篇。组件的通信组件一般来说有以下几种关系:父子关系隔代关系兄弟关系组件间经常会通信,Vue内置的通信手段一般有两种:ref:给元素或组件注册引用信息;$parent / $children:访问父/子实例。这两种方式都是直接得到组件的实例,然后直接调用组件......
  • 无界微前端(wujie):element-ui 弹框内使用select组件,弹出框位置异常解决方案 (主程序加载
    https://wujie-micro.github.io/doc/guide/ element-ui弹框内使用select组件,弹出框位置异常解决方案第一步:在子应用中: 以上3步就好啦!!!是不是很简单这个框架坑很多,希望对大家有帮助!!! ......
  • vue全家桶进阶之路43:Vue3 Element Plus el-form表单组件
    在ElementPlus中,el-form是一个表单组件,用于创建表单以便用户填写和提交数据。它提供了许多内置的验证规则和验证方法,使表单验证更加容易。使用el-form组件,您可以将表单控件组织在一起,并对表单进行验证,以确保提交的数据符合预期的格式和要求。该组件具有以下特性:支持内置......
  • Android UI组件
    1.TextView知识点:autoLink:文本自动识别为web超链接、email地址等——第五章AcitonBar用法:自定义ActionBar——第四章创建Acticity选项菜单:让返回键在ActionBar中显示后,重写onOptionsItemSelected——第四章创建,注册监听器,实现按钮功能——第四章布局:<?xmlversion="1.0......
  • 如何在html页面引入Element组件
    相关步骤1、引入相关链接<linkrel="stylesheet"href="https://unpkg.com/[email protected]/lib/theme-chalk/index.css"><scriptsrc="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><scriptsrc="https://un......