[Рефакторинг] Компонент обратного отсчета апплета WeChat

внешний интерфейс GitHub Апплет WeChat

Вспоминая, что когда я только пришел в компанию в качестве стажера четыре месяца назад, я инкапсулировал компонент обратного отсчета, примененный к небольшой программе.

Ссылка здесь:Компонент обратного отсчета апплета WeChat

Глядя на предыдущую реализацию с текущей точки зрения, можно сказать, что это кусок плохого кода, который невозможно прочитать. Так что воспользуйтесь этой возможностью, чтобы реорганизовать предыдущие компоненты.

Рефакторинг старого кода

В исходном компоненте есть свойство initDuration и 3 метода, 3 метода: countDown, format и runCountDown.

свойство initDuration

Сначала нам нужны три атрибута страницы, которые помогут выполнить следующий код, их имена и содержимое следующие:

timer: null, // 存储setInterval的ID
flag: false, // 倒计时是否结束的标志
num: 0 // 过去的秒数

В новом методе обратного вызова свойства initDuration мы инкапсулируем метод clearTimer, метод инициализации init и выполняем обратный отсчет.

initDuration: {
  type: Number,
  value: 0,
  observer: function (newVal) {
    if (this.timer) {
      this.clearTimer()
    }
  
    this.init() // 重置num和flag
    this.runCountDown(newVal)
  }
},

Следует отметить, что когда значение входящего свойства является значением по умолчанию, таким как 0 здесь, обратный вызов наблюдателя не будет запущен.

/**
 * 初始化函数
 */
init: function () {
  this.flag = false
  this.num = 0
}

/**
 * 清空计时器
 */
clearTimer: function () {
  clearInterval(this.timer)
  this.timer = null
}

метод обратного отсчета

Метод countDown принимает параметр в виде секунд обратного отсчета и возвращает строку обратного отсчета. В этом методе не так много изменений, изменено лишь некоторое форматирование кода. следующим образом:

/**
 * 计算倒计时
 * @param {Number} duration - 秒数时间差
 * @returns {string} 倒计时的字符串
 */
countDown: function (duration) {
  if (duration <= 0) {
    this.setFlag(true) // 将flag属性设为true
    return '00:00:00' // 返回默认时间设置
  }

  let seconds = this._format(duration % 60)
  let minutes = Math.floor(duration / 60)
  minutes = minutes >= 60 ? this._format(minutes % 60) : this._format(minutes)
  let hours = this._format(Math.floor(duration / 3600))

  return `${hours}:${minutes}:${seconds}`
},

метод форматирования

Роль метода формата очень проста, то есть решить проблему цифрового отображения менее 10.

/**
 * 格式化小于10的数字
 * @param {Number} time - 小于10的数字
 * @returns {string} 格式化后的字符串
 */
format: function (time) {
  return time >= 10 ? time : `0${time}`
},

метод runCountDown

Изменения в методе runCountDown относительно велики, а логика в исходном коде хаотична, перемежается множеством неактуальных кодов, на самом деле их нужно инкапсулировать для достижения цели развязки.

runCountDown: function (initDuration) {
  // 第一次给倒计时赋值 this.setData({ countDownStr })
  this.setCountDownTime(this.countDown(initDuration))

  // 每一秒更新一次倒计时
  this.timer = setInterval(() => {
    if (this.flag == true) { // 倒计时结束
      clearInterval(this.timer)

      return undefined
    }

    this.addNum() // this.num += 1
    this.setCountDownTime(this._countDown(initDuration - this.num))
  }, 1000)
},

Добавить новые функции

В нашем исходном компоненте обратного отсчета отсутствуют некоторые функции, например, входящее время может быть только в секундах, а после окончания обратного отсчета отображается только 00:00:00, если входящее значение равно 0, оно не будет инициализировано (это баг . ). Итак, нам нужно добавить следующие новые функции:

  • Поддержка пользовательского обратного отсчета после окончания реалистичной строки.
  • Исправьте ошибку, из-за которой входящее значение равно 0.
  • Входящее время может быть количеством секунд или строкой времени UTC.

Пользовательский конец строки

В компоненте обратного отсчета именно свойство this.data.countDownTime отображает строку обратного отсчета. Итак, в конце установите значение свойства countDownTime для входящей строки. Во-первых, инкапсулируйте метод присваивания

setEndContent: function (countDownTime) {
  if (countDownTime) {
    this.setData({ countDownTime })
  }
}

Затем добавьте новое свойство к компоненту какendContent.

endContent: {
  type: String,
  value: '00:00:00'
}

Затем, в конце обратного отсчета, вызовите наш метод присваивания, который является функцией обратного вызова таймера метода runCountDown.

this.timer = setInterval(() => {
  if (this.flag == true) {
    clearInterval(this.timer)
    
    this.setEndContent(this.properties.endContent) // 设置结束字符串
    
    return undefined
  }
    
  this.addNum()
  this.setCountDownTime(this._countDown(initDuration - this.num))
}, 1000)

Таким образом, пользовательская строка будет успешной, и при использовании компонента можно будет передать значение по умолчанию.

Исправить ошибку, что входящее значение равно 0

Эта проблема возникает из-за того, что когда входящее свойство является значением по умолчанию, функция обратного вызова наблюдателя не будет вызываться, поэтому нам нужно использовать свойство компонента.attachedФункции жизненного цикла.

attached: function () {
  if (this.properties.initDuration <= 0) {
    // 如果传入值为零时不会调用observer回调,则直接从这里展示倒计时结束
    this.setEndContent(this.properties.endContent)
  }
}

Строка времени UTC может быть передана в

Для краткости мы не будем добавлять новые свойства в компонент, а все же будем использовать свойство initDuration, поэтому нам нужно изменить его тип с Number на null (этот пункт апплета недостаточно силен, чтобы выбирать несколько типов.) . После изменения типа нам нужно инкапсулировать метод, который анализирует строку времени UTC в секундах обратного отсчета.

parseDate: function (date) {
  if (typeof date == 'string') {
    // 将传进来的时间减去现在的时间,得到的结果便和直接传进数字值相同
    return Math.floor((+new Date(date) / 1000)) - Math.floor((+new Date / 1000))
  }
  
  return date
}

При вызове в обратном вызове наблюдателя следующим образом:

initDuration: {
  type: null,
  observer: function (newVal) {
    if (this.timer) {
      this._clearTimer()
    }
  
    this._init()
    this._runCountDown(this.parseDate(newVal)) // 在这里调用parseData方法
  }
}

Суммировать

Во время этого процесса рефакторинга я увидел, что предыдущая муфта кода была слишком серьезной, и она соответствовала только ситуации импровизации. Если вы хотите добавить функции на этой основе, стоимость очень высока, поэтому внутренняя логика разделена. Не только легко читать и понимать, но также легко расширить функцию в будущем. Поэтому после рефакторинга мы добавили две новые функции. Я надеюсь, что эта статья может помочь вам.

Код компонента обратного отсчета:GitHub.com/me log UO/ Я хочу купить…
Вы можете скопировать папку «обратный отсчет» непосредственно в каталог проекта для использования.
Добро пожаловать, чтобы поставить лайк, подписаться, пометить, разветвить и, конечно же, прорекламировать.