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

Lit — это современный веб-фреймворк, который предоставляет декларативный способ создания компонентов на JavaScript. Одной из важных задач при разработке интерфейсов является корректное отображение дат, чисел и валют в зависимости от локали пользователя. Lit не накладывает ограничений на использование стандартных возможностей JavaScript, включая Intl API, что позволяет гибко форматировать данные прямо внутри компонентов.


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

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

Пример использования:

import { LitElement, html, css } from 'lit';

class DateFormatter extends LitElement {
  static properties = {
    date: { type: Date },
    locale: { type: String }
  };

  constructor() {
    super();
    this.date = new Date();
    this.locale = 'ru-RU';
  }

  formatDate(date) {
    return new Intl.DateTimeFormat(this.locale, {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      weekday: 'long'
    }).format(date);
  }

  render() {
    return html`<p>Дата: ${this.formatDate(this.date)}</p>`;
  }
}

customElements.define('date-formatter', DateFormatter);

В этом примере:

  • locale определяет язык отображения.
  • Параметры year, month, day и weekday задают детализацию формата.
  • Результат автоматически обновляется при изменении свойств компонента.

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

Числа могут отображаться с учетом локали, фиксированного числа десятичных знаков и разделителей тысяч. Для этого используется Intl.NumberFormat.

Пример с Lit:

import { LitElement, html } from 'lit';

class NumberFormatter extends LitElement {
  static properties = {
    value: { type: Number },
    locale: { type: String }
  };

  constructor() {
    super();
    this.value = 1234567.89;
    this.locale = 'ru-RU';
  }

  formatNumber(value) {
    return new Intl.NumberFormat(this.locale, {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2
    }).format(value);
  }

  render() {
    return html`<p>Число: ${this.formatNumber(this.value)}</p>`;
  }
}

customElements.define('number-formatter', NumberFormatter);

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

  • minimumFractionDigits и maximumFractionDigits позволяют контролировать количество знаков после запятой.
  • Локаль автоматически учитывает разделители тысяч и десятичные разделители.

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

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

Пример:

import { LitElement, html } from 'lit';

class CurrencyFormatter extends LitElement {
  static properties = {
    amount: { type: Number },
    currency: { type: String },
    locale: { type: String }
  };

  constructor() {
    super();
    this.amount = 12345.67;
    this.currency = 'RUB';
    this.locale = 'ru-RU';
  }

  formatCurrency(amount) {
    return new Intl.NumberFormat(this.locale, {
      style: 'currency',
      currency: this.currency,
      minimumFractionDigits: 2,
      maximumFractionDigits: 2
    }).format(amount);
  }

  render() {
    return html`<p>Сумма: ${this.formatCurrency(this.amount)}</p>`;
  }
}

customElements.define('currency-formatter', CurrencyFormatter);

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

  • style: 'currency' включает отображение символа валюты.
  • currency задает код валюты (например, USD, EUR, RUB).
  • Локаль определяет расположение символа (до или после числа) и формат разделителей.

Динамическое обновление форматов

Lit позволяет автоматически обновлять форматирование при изменении свойств. Если свойство locale или currency изменится, компонент автоматически перерисует содержимое без дополнительного кода.

Пример динамической локали:

this.locale = 'en-US'; // автоматически обновит формат даты и чисел
this.requestUpdate();   // при необходимости вызвать вручную

Использование шаблонных функций

Для упрощения форматирования часто создаются утилитарные методы или даже функции-шаблоны внутри компонентов:

html`<p>${this.formatNumber(this.value)}</p>`
html`<p>${this.formatCurrency(this.amount)}</p>`
html`<p>${this.formatDate(this.date)}</p>`

Это делает код компактным и легко поддерживаемым, а также сохраняет декларативный стиль, характерный для Lit.


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

  • Создание экземпляров Intl.DateTimeFormat или Intl.NumberFormat внутри метода render() может быть ресурсоёмким при больших списках. Рекомендуется кешировать форматтеры как свойства класса.
  • Для часто обновляемых значений следует использовать мемоизацию форматтеров по комбинации локали и настроек.
  • Для больших приложений стоит вынести функции форматирования в отдельные утилиты, чтобы избежать дублирования кода.

Примеры комплексного применения

render() {
  return html`
    <div>
      <p>Дата: ${this.formatDate(this.date)}</p>
      <p>Число: ${this.formatNumber(this.value)}</p>
      <p>Сумма: ${this.formatCurrency(this.amount)}</p>
    </div>
  `;
}

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