Применение принципов программирования мини-приложений к примеру проекта

Домен приложения

Чтобы показать способ программирования с помощью мини-приложения, примененный к веб-приложению, мне нужна была небольшая, но достаточно полная идея приложения. Высокоинтенсивная интервальная тренировка (HIIT) — это стратегия кардиотренировок, состоящая из чередующихся наборов коротких периодов интенсивных анаэробных упражнений с менее интенсивными периодами восстановления. Во многих тренировках HIIT используются таймеры HIIT, например, эта 30-минутная онлайн-сессия с канала YouTube The Body Coach TV .

Онлайн-сеанс HIIT-тренировки с зеленым таймером высокой интенсивности.
Активный период.
Онлайн-сеанс HIIT-тренировки с красным таймером низкой интенсивности.
Период покоя.

Пример приложения HIIT Time

Для этой главы я создал базовый пример такого приложения таймера HIIT, метко названного "HIIT Time", которое позволяет пользователю определять и управлять различными таймерами, всегда состоящими из интервала высокой и низкой интенсивности, а затем выбирать один из них для сеанса тренировки. Это отзывчивое приложение с панелью навигации, панелью вкладок и тремя страницами:

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

Следующие скриншоты дают представление о приложении.

Пример приложения HIIT Time в портретном режиме.
Время HIIT Вкладка «Тренировка» в портретном режиме.
Пример приложения HIIT Time в ландшафтном режиме.
Время HIIT Вкладка «Тренировка» в ландшафтном режиме.
Пример приложения HIIT Time, демонстрирующий управление таймером.
Управление таймером времени HIIT.

Структура приложения

Как было сказано выше, приложение состоит из панели навигации, панели вкладок и трех страниц, расположенных в сетке. Панель навигации и панель вкладок реализованы как iframe с контейнером <div> между ними и еще тремя iframe для страниц, из которых один всегда виден и зависит от активного выбора на панели вкладок. Последний iframe, указывающий на about:blank служит для динамически создаваемых страниц внутри приложения, которые необходимы для изменения существующих таймеров или создания новых. Я называю этот шаблон многостраничным одностраничным приложением (MPSPA).

Представление HTML-структуры приложения в Chrome DevTools, показывающее, что оно состоит из шести iframe: одного для панели навигации, одного для панели вкладок и трех сгруппированных для каждой страницы приложения, а также последнего iframe-заполнителя для динамических страниц.
Приложение состоит из шести фреймов.

Разметка lit-html на основе компонентов

Структура каждой страницы реализована как lit-html scaffold, который динамически оценивается во время выполнения. Для справки о lit-html, это эффективная, выразительная, расширяемая библиотека шаблонов HTML для JavaScript. Используя ее непосредственно в файлах HTML, модель ментального программирования напрямую ориентирована на вывод. Как программист, вы пишете шаблон того, как будет выглядеть конечный вывод, а lit-html затем динамически заполняет пробелы на основе ваших данных и подключает прослушиватели событий. Приложение использует сторонние пользовательские элементы, такие как <sl-progress-ring> Shoelace или самореализованный пользовательский элемент под названием <human-duration> . Поскольку пользовательские элементы имеют декларативный API (например, атрибут percentage кольца прогресса), они хорошо работают вместе с lit-html, как вы можете видеть в листинге ниже.

<div>
  <button class="start" @click="${eventHandlers.start}" type="button">
    ${strings.START}
  </button>
  <button class="pause" @click="${eventHandlers.pause}" type="button">
    ${strings.PAUSE}
  </button>
  <button class="reset" @click="${eventHandlers.reset}" type="button">
    ${strings.RESET}
  </button>
</div>

<div class="progress-rings">
  <sl-progress-ring
    class="sets"
    percentage="${Math.floor(data.sets/data.activeTimer.sets*100)}"
  >
    <div class="progress-ring-caption">
      <span>${strings.SETS}</span>
      <span>${data.sets}</span>
    </div>
  </sl-progress-ring>
</div>
Три кнопки и кольцо хода.
Визуализированный раздел страницы, соответствующий разметке выше.

Модель программирования

Каждая страница имеет соответствующий класс Page , который наполняет разметку lit-html жизнью, предоставляя реализации обработчиков событий и предоставляя данные для каждой страницы. Этот класс также поддерживает методы жизненного цикла, такие как onShow() , onHide() , onLoad() и onUnload() . Страницы имеют доступ к хранилищу данных, которое служит для совместного использования опционально сохраняемого состояния на каждой странице и глобального состояния. Все строки управляются централизованно, поэтому встроена интернационализация. Маршрутизация обрабатывается браузером по сути бесплатно, поскольку все, что делает приложение, это переключает видимость iframe и для динамически созданных страниц изменяет атрибут src заполнителя iframe. В примере ниже показан код для закрытия динамически созданной страницы.

import Page from '../page.js';

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
Страница приложения реализована в виде iframe.
Навигация происходит из iframe в iframe.

Стайлинг

Стилизация страниц выполняется на каждой странице в ее собственном CSS-файле с областью действия. Это означает, что к элементам обычно можно напрямую обращаться по их именам элементов, поскольку не может возникнуть никаких конфликтов с другими страницами. Глобальные стили добавляются к каждой странице, поэтому центральные настройки, такие как font-family или box-sizing не нужно объявлять повторно. Здесь также определяются темы и параметры темного режима. В приведенном ниже списке показаны правила для страницы настроек, которая размещает различные элементы формы на сетке.

main {
  max-width: 600px;
}

form {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-gap: 0.5rem;
  margin-block-end: 1rem;
}

label {
  text-align: end;
  grid-column: 1 / 2;
}

input,
select {
  grid-column: 2 / 3;
}
Страница настроек приложения HIIT Time, отображающая форму в виде сетки.
Каждая страница — это свой собственный мир. Стилизация происходит напрямую с именами элементов.

Блокировка экрана

Во время тренировки экран не должен выключаться. В браузерах, которые это поддерживают, HIIT Time реализует это через блокировку экрана . Фрагмент ниже показывает, как это делается.

if ('wakeLock' in navigator) {
  const requestWakeLock = async () => {
    try {
      page.shared.wakeLock = await navigator.wakeLock.request('screen');
      page.shared.wakeLock.addEventListener('release', () => {
        // Nothing.
      });
    } catch (err) {
      console.error(`${err.name}, ${err.message}`);
    }
  };
  // Request a screen wake lock…
  await requestWakeLock();
  // …and re-request it when the page becomes visible.
  document.addEventListener('visibilitychange', async () => {
    if (
      page.shared.wakeLock !== null &&
      document.visibilityState === 'visible'
    ) {
      await requestWakeLock();
    }
  });
}

Тестирование приложения

Приложение HIIT Time доступно на GitHub . Вы можете поиграть с демо в новом окне или прямо в iframe, встроенном ниже, который имитирует мобильное устройство.

Благодарности

Эту статью рецензировали Джо Медли , Кейс Баскес , Милица Михайлия , Алан Кент и Кейт Гу.

,

Домен приложения

Чтобы показать способ программирования с помощью мини-приложения, примененный к веб-приложению, мне нужна была небольшая, но достаточно полная идея приложения. Высокоинтенсивная интервальная тренировка (HIIT) — это стратегия кардиотренировок, состоящая из чередующихся наборов коротких периодов интенсивных анаэробных упражнений с менее интенсивными периодами восстановления. Во многих тренировках HIIT используются таймеры HIIT, например, эта 30-минутная онлайн-сессия с канала YouTube The Body Coach TV .

Онлайн-сеанс HIIT-тренировки с зеленым таймером высокой интенсивности.
Активный период.
Онлайн-сеанс HIIT-тренировки с красным таймером низкой интенсивности.
Период покоя.

Пример приложения HIIT Time

Для этой главы я создал базовый пример такого приложения таймера HIIT, метко названного "HIIT Time", которое позволяет пользователю определять и управлять различными таймерами, всегда состоящими из интервала высокой и низкой интенсивности, а затем выбирать один из них для сеанса тренировки. Это отзывчивое приложение с панелью навигации, панелью вкладок и тремя страницами:

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

Следующие скриншоты дают представление о приложении.

Пример приложения HIIT Time в портретном режиме.
Время HIIT Вкладка «Тренировка» в портретном режиме.
Пример приложения HIIT Time в ландшафтном режиме.
Время HIIT Вкладка «Тренировка» в ландшафтном режиме.
Пример приложения HIIT Time, демонстрирующий управление таймером.
Управление таймером времени HIIT.

Структура приложения

Как было сказано выше, приложение состоит из панели навигации, панели вкладок и трех страниц, расположенных в сетке. Панель навигации и панель вкладок реализованы как iframe с контейнером <div> между ними и еще тремя iframe для страниц, из которых один всегда виден и зависит от активного выбора на панели вкладок. Последний iframe, указывающий на about:blank служит для динамически создаваемых страниц внутри приложения, которые необходимы для изменения существующих таймеров или создания новых. Я называю этот шаблон многостраничным одностраничным приложением (MPSPA).

Представление HTML-структуры приложения в Chrome DevTools, показывающее, что оно состоит из шести iframe: одного для панели навигации, одного для панели вкладок и трех сгруппированных для каждой страницы приложения, а также последнего iframe-заполнителя для динамических страниц.
Приложение состоит из шести фреймов.

Разметка lit-html на основе компонентов

Структура каждой страницы реализована как lit-html scaffold, который динамически оценивается во время выполнения. Для справки о lit-html, это эффективная, выразительная, расширяемая библиотека шаблонов HTML для JavaScript. Используя ее непосредственно в файлах HTML, модель ментального программирования напрямую ориентирована на вывод. Как программист, вы пишете шаблон того, как будет выглядеть конечный вывод, а lit-html затем динамически заполняет пробелы на основе ваших данных и подключает прослушиватели событий. Приложение использует сторонние пользовательские элементы, такие как <sl-progress-ring> Shoelace или самореализованный пользовательский элемент под названием <human-duration> . Поскольку пользовательские элементы имеют декларативный API (например, атрибут percentage кольца прогресса), они хорошо работают вместе с lit-html, как вы можете видеть в листинге ниже.

<div>
  <button class="start" @click="${eventHandlers.start}" type="button">
    ${strings.START}
  </button>
  <button class="pause" @click="${eventHandlers.pause}" type="button">
    ${strings.PAUSE}
  </button>
  <button class="reset" @click="${eventHandlers.reset}" type="button">
    ${strings.RESET}
  </button>
</div>

<div class="progress-rings">
  <sl-progress-ring
    class="sets"
    percentage="${Math.floor(data.sets/data.activeTimer.sets*100)}"
  >
    <div class="progress-ring-caption">
      <span>${strings.SETS}</span>
      <span>${data.sets}</span>
    </div>
  </sl-progress-ring>
</div>
Три кнопки и кольцо хода.
Визуализированный раздел страницы, соответствующий разметке выше.

Модель программирования

Каждая страница имеет соответствующий класс Page , который наполняет разметку lit-html жизнью, предоставляя реализации обработчиков событий и предоставляя данные для каждой страницы. Этот класс также поддерживает методы жизненного цикла, такие как onShow() , onHide() , onLoad() и onUnload() . Страницы имеют доступ к хранилищу данных, которое служит для совместного использования опционально сохраняемого состояния на каждой странице и глобального состояния. Все строки управляются централизованно, поэтому встроена интернационализация. Маршрутизация обрабатывается браузером по сути бесплатно, поскольку все, что делает приложение, это переключает видимость iframe и для динамически созданных страниц изменяет атрибут src заполнителя iframe. В примере ниже показан код для закрытия динамически созданной страницы.

import Page from '../page.js';

const page = new Page({
  eventHandlers: {
    back: (e) => {
      e.preventDefault();
      window.top.history.back();
    },
  },
});
Страница приложения реализована в виде iframe.
Навигация происходит из iframe в iframe.

Стайлинг

Стилизация страниц выполняется на каждой странице в ее собственном CSS-файле с областью действия. Это означает, что к элементам обычно можно напрямую обращаться по их именам элементов, поскольку не может возникнуть никаких конфликтов с другими страницами. Глобальные стили добавляются к каждой странице, поэтому центральные настройки, такие как font-family или box-sizing не нужно объявлять повторно. Здесь также определяются темы и параметры темного режима. В приведенном ниже списке показаны правила для страницы настроек, которая размещает различные элементы формы на сетке.

main {
  max-width: 600px;
}

form {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-gap: 0.5rem;
  margin-block-end: 1rem;
}

label {
  text-align: end;
  grid-column: 1 / 2;
}

input,
select {
  grid-column: 2 / 3;
}
Страница настроек приложения HIIT Time, отображающая форму в виде сетки.
Каждая страница — это свой собственный мир. Стилизация происходит напрямую с именами элементов.

Блокировка экрана

Во время тренировки экран не должен выключаться. В браузерах, которые это поддерживают, HIIT Time реализует это через блокировку экрана . Фрагмент ниже показывает, как это делается.

if ('wakeLock' in navigator) {
  const requestWakeLock = async () => {
    try {
      page.shared.wakeLock = await navigator.wakeLock.request('screen');
      page.shared.wakeLock.addEventListener('release', () => {
        // Nothing.
      });
    } catch (err) {
      console.error(`${err.name}, ${err.message}`);
    }
  };
  // Request a screen wake lock…
  await requestWakeLock();
  // …and re-request it when the page becomes visible.
  document.addEventListener('visibilitychange', async () => {
    if (
      page.shared.wakeLock !== null &&
      document.visibilityState === 'visible'
    ) {
      await requestWakeLock();
    }
  });
}

Тестирование приложения

Приложение HIIT Time доступно на GitHub . Вы можете поиграть с демо в новом окне или прямо в iframe, встроенном ниже, который имитирует мобильное устройство.

Благодарности

Эту статью рецензировали Джо Медли , Кейс Баскес , Милица Михайлия , Алан Кент и Кейт Гу.