Форматирование дат, чисел и валют

Riot.js — легковесный фреймворк для создания реактивных веб-компонентов. Одной из часто используемых задач в интерфейсах является корректное отображение данных: дат, чисел и денежных сумм. Riot.js предоставляет возможности для интеграции стандартных JavaScript-методов и библиотек, что позволяет гибко форматировать значения прямо в шаблонах компонентов.


Форматирование дат

В Riot.js данные для отображения чаще всего задаются через props или state. Для работы с датами используется объект Date и методы международной локализации Intl.DateTimeFormat.

<date-display>
  <p>{ formattedDate }</p>

  <script>
    export default {
      formattedDate: new Intl.DateTimeFormat('ru-RU', {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit'
      }).format(new Date())
    }
  </script>
</date-display>

Ключевые моменты:

  • Intl.DateTimeFormat позволяет задавать локаль ('ru-RU') и различные параметры отображения (year, month, weekday и т. д.).
  • Форматирование производится один раз при инициализации компонента, но можно создавать вычисляемые свойства для динамических обновлений.

Для динамически обновляемой даты используется реактивное свойство:

<clock>
  <p>{ currentTime }</p>

  <script>
    export default {
      currentTime: new Intl.DateTimeFormat('ru-RU', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      }).format(new Date()),

      onMounted() {
        this.timer = setInterval(() => {
          this.currentTime = new Intl.DateTimeFormat('ru-RU', {
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
          }).format(new Date());
          this.update();
        }, 1000);
      },

      onBeforeUnmount() {
        clearInterval(this.timer);
      }
    }
  </script>
</clock>

Форматирование чисел

Для чисел также используется объект Intl.NumberFormat, который позволяет управлять разрядностью, разделителями и локализацией:

<number-display>
  <p>{ formattedNumber }</p>

  <script>
    export default {
      formattedNumber: new Intl.NumberFormat('ru-RU', {
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      }).format(1234567.89)
    }
  </script>
</number-display>

Особенности:

  • minimumFractionDigits и maximumFractionDigits позволяют управлять количеством цифр после запятой.
  • Локаль 'ru-RU' задаёт правильный формат разделителей тысяч и десятичной части.

Для больших приложений удобно создавать фильтры или утилиты, чтобы не дублировать форматирование в каждом компоненте:

// utils/format.js
export function formatNumber(value, locale = 'ru-RU', options = {}) {
  return new Intl.NumberFormat(locale, options).format(value);
}

И использовать внутри компонента:

import { formatNumber } from './utils/format.js';

<p>{ formatNumber(9876543.21) }</p>

Форматирование валют

Riot.js позволяет применять международный стандарт Intl.NumberFormat и для денежных значений. Основное преимущество — автоматическое добавление символа валюты и правильное округление.

<price-display>
  <p>{ formattedPrice }</p>

  <script>
    export default {
      formattedPrice: new Intl.NumberFormat('ru-RU', {
        style: 'currency',
        currency: 'RUB',
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      }).format(1599.95)
    }
  </script>
</price-display>

Особенности валютного форматирования:

  • Параметр style: 'currency' активирует режим отображения валют.
  • Свойство currency принимает трехсимвольный код ISO (например, 'USD', 'EUR', 'RUB').
  • Настройка minimumFractionDigits и maximumFractionDigits гарантирует одинаковое количество знаков после запятой.

Для динамических цен удобно использовать реактивные свойства:

<product-price>
  <p>{ formattedPrice }</p>

  <script>
    export default {
      price: 2999.9,

      get formattedPrice() {
        return new Intl.NumberFormat('ru-RU', {
          style: 'currency',
          currency: 'RUB'
        }).format(this.price);
      }
    }
  </script>
</product-price>

Здесь свойство formattedPrice автоматически обновляется при изменении price.


Создание универсальных фильтров

В Riot.js можно создавать глобальные или локальные фильтры для повторного использования форматирования:

// filters.js
export const filters = {
  formatDate: (date) => new Intl.DateTimeFormat('ru-RU', { dateStyle: 'long', timeStyle: 'short' }).format(date),
  formatNumber: (num) => new Intl.NumberFormat('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(num),
  formatCurrency: (num, currency = 'RUB') => new Intl.NumberFormat('ru-RU', { style: 'currency', currency }).format(num)
};

Применение в компоненте:

import { filters } from './filters.js';

<p>{ filters.formatDate(new Date()) }</p>
<p>{ filters.formatNumber(1234567.89) }</p>
<p>{ filters.formatCurrency(1599.95, 'USD') }</p>

Это повышает читаемость и поддерживаемость кода, особенно в крупных проектах с большим количеством отображаемых данных.


Поддержка локалей

Riot.js полностью полагается на стандарт Intl для локализации. Важно учитывать:

  • Поддержка локали зависит от браузера. В современных браузерах большинство локалей уже встроены.
  • Для старых браузеров можно использовать полифиллы, например Intl.js.
  • Локаль задаётся везде одинаково: new Intl.NumberFormat('ru-RU', {...}) или new Intl.DateTimeFormat('ru-RU', {...}).

Рекомендации по производительности

  • Форматирование больших массивов данных лучше делать до передачи в компонент, чтобы избежать лишних вызовов Intl на каждый рендер.
  • Для часто обновляемых дат или чисел использовать вычисляемые свойства или методы, вызываемые через update(), вместо постоянного пересоздания объектов.
  • Для мультивалютных и мультилокальных приложений следует централизовать утилиты форматирования для консистентного отображения данных.