This is the 19th day of my participation in the Genwen Challenge

There is another direction worth playing in the refactoring process, which is to keep removing the introduced third party components one by one.

Today, I had an idea to make a countdown component by myself. The goal is to replace vue3-clock-countdown.

I looked at the source code for the vue3-clock-countdown component and it wasn’t that hard (no disrespect to the original author of course!). .

Note: I would also recommend that the original author add event related features to make it complete.

According to the effect

Without further ado, let’s look at the display effect:

  • Display “day – time – minute – second” :

  • Display “time-min-second” :

  • Display “minute-second” :

The logic of production is to keep everything simple, simple, simple.

layout

For this layout I mainly use NCard:

Specific code:

<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>
Copy the code

So, we’re pretty much done with the header.

In the display “day – hour – minute – second” section, directly use the “layout” component, and display several NGi according to COLs:

< n - the grid - gap x = "12" : cols = "cols" > < n - gi v - if = "cols = = 4" > < n - card: the title = "formatTime (days)" size = "large" > day < / n - card > < / n - gi > < n - gi v - if = "cols > = 3" > < n - card "title =" formatTime (hours) "size =" large "> when < / 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"> seconds </n-card> </n-gi> </n-grid>Copy the code

It is too simple to say:

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

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

  return 2;
},
Copy the code

You can use v-for to reduce duplicate code, and then use V-if to determine whether to display. However, in the official document of Vue, the following restrictions are clearly written: Never use V-if and V-for on the same element.

To filter items in a list (for example, v-for=”user in users” v-if=” user.isactive “). In this case, replace Users with a calculated property (such as activeUsers) and have it return the filtered list.

See: v3.cn.vuejs.org/style-guide…

Logical processing

In the logical part, there are three main aspects of data to consider:

  1. Time and countdown logic
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'); }}}Copy the code

Data moments such as seconds, minutes, hours, and days change with currentTime, so they are computed. In Mounted, the countdown is automatically executed when the component is loaded.

  1. Time and title

This I refer to the original author’s method, directly use the Provide/Inject method, save the assignment and import in other places.

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

Because I want to pass some properties, such as height, outside of the component, add another way to customize.

Event handling is the difference between us and the original author. We really click exit or countdown to pass the event out.

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

summary

Now, with the custom component, we can remove the vue3-clock-countdown component.

You can continue to optimize your own components and remove third-party components to give your project more control. To be continued!

The code has been synced to Github: github.com/fanly/fanly…