Electron+Vue3 MAC 版日历开发记录(19)——自制倒计时组件__Vue.js__Electron
发布于 3 年前 作者 banyungong 816 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

这是我参与更文挑战的第19天,活动详情查看: 更文挑战

在重构过程中,我们还有一个方向值得去折腾,那就是不断把引入的第三方组件一个个想办法移除。

今天突发奇想开始自己折腾做一个倒计时的组件,目标是想替换了 vue3-clock-countdown

我看了看这个 vue3-clock-countdown 组件的源代码,貌似也没那么难 (当然不是不尊重原作者!)。

注:我也想推荐原作者把事件相关功能加上,这样才显得完整。

显示效果

废话不多说,先看看显示效果:

  • 显示「天-时-分-秒」:

  • 显示「时-分-秒」:

  • 显示「分-秒」:

制作的逻辑就是保持所有东西:简洁、简洁、简洁。

布局

这个布局我主要使用 NCard

具体代码:

<template>
  <n-card :title="title" :bordered="false" :style="style">
    <template #header-extra>
      <n-button
        text
        style="font-size: 24px;"
        @click="$emit('finish')"
      >
        <n-icon>
          <times-circle-regular-icon />
        </n-icon>
      </n-button>
    </template>
    <n-grid x-gap="12" :cols="cols">
      ...
    </n-grid>
  </n-card>
</template>

这样,基本把 header 部分解决了。

在显示「天-时-分-秒」部分,直接使用了「布局」组件,再根据 cols 来定显示几个 NGi

<n-grid x-gap="12" :cols="cols">
  <n-gi v-if="cols == 4">
    <n-card :title="formatTime(days)" size="large">天</n-card>
  </n-gi>
  <n-gi  v-if="cols >= 3">
    <n-card :title="formatTime(hours)" size="large">时</n-card>
  </n-gi>
  <n-gi>
    <n-card :title="formatTime(minutes)" size="large">分</n-card>
  </n-gi>
  <n-gi>
    <n-card :title="formatTime(seconds)" size="large">秒</n-card>
  </n-gi>
</n-grid>

具体是不是显示「天」和「时」,太简单了,都不好意思说了:

cols(): number {
  if (this.days > 0) {
    return 4;
  }

  if (this.hours > 0) {
    return 3;
  }

  return 2;
},

就四个布局,可以直接写出来,也不是什么不可以,一样的,这边完全可以用 v-for 来减少重复代码,然后用 v-if 来判断是否显示,但在 Vue 官网文档里,明确写了以下限制: 永远不要把 v-if 和 v-for 同时用在同一个元素上。

为了过滤一个列表中的项目 (比如 v-for=“user in users” v-if=“user.isActive”)。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。

详见:https://v3.cn.vuejs.org/style-guide/

逻辑处理

在逻辑部分,主要有三方面的数据需要考虑:

  1. 时间和倒计时逻辑
seconds(): number {
  return Math.floor((this.currentTime / 1000) % 60);
},
minutes(): number {
  return Math.floor((this.currentTime / 1000 / 60) % 60);
},
hours(): number {
  return Math.floor((this.currentTime / (1000 * 60 * 60)) % 24);
},
days(): number {
  return Math.floor(this.currentTime / (1000 * 60 * 60 * 24));
},

...

mounted() {
  setTimeout(this.countdown, 1000);
},
  methods: {
    formatTime(value: number): string {
      if (value < 10) {
        return '0' + value;
    }
    return value.toString();
  },
  countdown () {
    this.currentTime = Date.parse(this.deadline) - Date.parse(new Date());
    if (this.currentTime > 0) {
      setTimeout(this.countdown, this.speed);
    } else {
      this.$emit('finish');
    }
  }
}

seconds、minutes、hours、days 这些数据时刻随着 currentTime 的变化而变化,所以放在了 computed 里;倒计时直接在组件加载时,可以自动进入倒计时执行,所以放在 mounted 里。

  1. 时间和标题

这个我参考原作者的方式,直接用的 Provide / Inject 方式,省了在其他地方赋值和引入。

setup() {
  const deadline = inject('deadline');
  const title = inject('title', '');
  return {
    deadline,
    title,
  };
},
  1. props 和 emits
  props: {
    speed: {
      type: Number,
      default: 1000
    },
    height: Number,
  },
  emits: [
    'finish',
  ],

因为我想把一些属性,如高度 height 这个可以交给组件外部传入,增加可自定义多一种方式。

事件处理,是我们和原作者不一样的地方,真实的在点击退出或者倒计时到了,把事件传出去。

  <n-button
    text
    style="font-size: 24px;"
    @click="$emit('finish')"
  >

小结

好了,有了自定义组件,我们就可以移除 vue3-clock-countdown 组件。

后续可以不断优化自己开发的组件,也不断移除第三方组件,让自己的项目越来越可控。未完待续!

代码已同步到 github 上了:https://github.com/fanly/fanlymenu

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 叶梅树 原文链接:https://juejin.im/post/6975528302563819557

回到顶部