# 小程序+vant商品列表批量倒计时

# 倒计时效果


xcooo

项目需要用到商品批量倒计时,当时使用vant封装好的组件CountDown (opens new window)编写

xcooo

# 由于我们需要自定义样式, 我们需要使用带有 插槽

xcooo

最开始写这个倒计时的时候没有考虑到使用当前服务器时间问题,只获取了本地时间 new Date().getTime(),然后发现这个不行,只要用户修改下手机本地时间,这个倒计时就不行了,有安全隐患,在网上也搜了一些相关知识,但都不尽人意,故想写这一篇文章避免大家再走我之前的弯路!

# 注: 由于我用了 子传父 通信方式, 封装成组件, 可能代码方法不一致, 主要看思路

废话不多少说,上代码

# 子组件wxml

<van-count-down use-slot time="{{ item.time }}" bind:change="onChange" data-item-index="{{index}}">
          <text class="seckill-date-time">2020</text>
          <text class="seckill-time-line">-</text>
          <text class="seckill-date-time">10</text>
          <text class="seckill-time-line">-</text>
          <text class="seckill-date-time">05</text>
          <text class="seckill-time-line notime-text"></text>
          <text class="seckill-date-time">{{item.timeData.hours}}</text>
          <text class="seckill-time-line">:</text>
          <text class="seckill-date-time">{{item.timeData.minutes}}</text>
          <text class="seckill-time-line">:</text>
          <text class="seckill-date-time">{{item.timeData.seconds}}</text>
</van-count-down>
1
2
3
4
5
6
7
8
9
10
11
12
13

需要将索引传递出去, 方便父组件获取批量商品时间

# 子组件js

onChange(e) {
      let params = {};
      const { itemIndex } = e.currentTarget.dataset;
      const { hours, minutes, seconds } = e.detail;

      params["hours"] = this.formate(hours);
      params["minutes"] = this.formate(minutes);
      params["seconds"] = this.formate(seconds);
      params["itemIndex"] = itemIndex;
      this.triggerEvent("handleTimeChange", params);
}
1
2
3
4
5
6
7
8
9
10
11

# 父组件wxml

<view class="product-warp">
      <block wx:for="{{lootingList}}" wx:key="index">
          <card-item item="{{item}}" index="{{index}}" bindhandleOpenDetail="handleOpenDetail" bindhandleTimeChange="handleTimeChange"></card-item>
      </block>
</view>
1
2
3
4
5

# 父组件js

  onLoad(options) {
    this.getGoodsList();
  },
  // 获取商品数据列表
   async getGoodsList() {
    if (!this.data.isHideLoadMore || this.data.isFinshed) {
      return;
    }
    this.setData({
      isHideLoadMore: false,
    });
    let lootingList = [];
    let noticeList = [];
    let res = await getSecKillProductList(this.QueryParams);
    if (!res) {
      this.setData({
        isHideLoadMore: true,
        isFinshed: false,
      });
      wx.showToast({
        title: "获取数据失败",
      });
      return;
    }
    this.setData({
      isHideLoadMore: true,
    });
    // 获取总条数
    const total = res.total;
    this.totalPages = Math.ceil(total / this.QueryParams.pageSize);

    let arr = res.list;
    let nowTime = new Date();
    let newArr = arr.map((item, index) => {
      if (this.QueryParams.type == 0) {
        // 秒杀开始时间小于等于当前本地时间
        let t1 = nowTime.getTime();
        let time = item.endTime.split("T")[0].split("-");
        item.endTime = item.endTime
          .replace("T", " ")
          .replace(/-/g, "/")
          .split(".")[0];
        let t2 = new Date(item.endTime).getTime();
        item["time"] = t2 - t1;
        item["timeData"] = {};
        // 补充年月日
        item["year"] = time[0];
        item["month"] = time[1];
        item["date"] = time[2].substring(0, 2);
      } else {
        // 批量格式化 秒杀开始时间
        item.startTime = getTimer(item.startTime);
      }
      return item;
    });
    if (this.QueryParams.type == 0) {
      lootingList = [...this.data.lootingList, ...newArr];
    } else {
      noticeList = [...this.data.noticeList, ...newArr];
    }
    this.setData({
      lootingList,
      noticeList,
    });
    if (arr.length < this.QueryParams.pageSize) {
      this.setData({
        isFinshed: true,
      });
    }
  },
  // 这个方法比较重要
  handleTimeChange(e) {
    let stringTimeData = "lootingList[" + e.detail.itemIndex + "].timeData";
    this.setData({
      [stringTimeData]: e.detail,
    });
  },
  // 格式化日期 年月日 时分秒
  getTimer(t) {
    let timeDate = {};
    let time = new Date(t);
    const year = time.getFullYear();
    const month = time.getMonth() + 1;
    const dates = time.getDate();
    let h = time.getHours();
    h = h < 10 ? "0" + h : h;
    let m = time.getMinutes();
    m = m < 10 ? "0" + m : m;
    let s = time.getSeconds();
    s = s < 10 ? "0" + s : s;
    timeDate = {
      year,
      month,
      dates,
      h,
      m,
      s,
    };
    return timeDate;
  },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
上次更新: 2020/10/27 下午11:58:10