Wie man einzelne Teile formatierter Zahlen für benutzerdefinierte Anzeige erhält
Formatierte Zahlen in Komponenten zerlegen, um benutzerdefiniertes Styling anzuwenden und komplexe Oberflächen zu erstellen
Einführung
Die format()-Methode gibt eine vollständige formatierte Zeichenkette wie "$1.234,56" oder "1,5 Mio." zurück. Dies funktioniert gut für einfache Anzeigen, aber Sie können einzelne Teile nicht unterschiedlich stylen. Sie können das Währungssymbol nicht fett machen, den Dezimalteil nicht anders einfärben oder bestimmten Komponenten kein benutzerdefiniertes Markup zuweisen.
JavaScript bietet die formatToParts()-Methode, um dieses Problem zu lösen. Anstatt eine einzelne Zeichenkette zurückzugeben, gibt sie ein Array von Objekten zurück, von denen jedes einen Teil der formatierten Zahl repräsentiert. Jeder Teil hat einen Typ wie currency, integer oder decimal und einen Wert wie $, 1234 oder .. Sie können diese Teile dann verarbeiten, um benutzerdefiniertes Styling anzuwenden, komplexe Layouts zu erstellen oder formatierte Zahlen in umfangreiche Benutzeroberflächen zu integrieren.
Warum formatierte Zeichenketten schwer anzupassen sind
Wenn Sie eine formatierte Zeichenkette wie "$1.234,56" erhalten, können Sie nicht einfach erkennen, wo das Währungssymbol endet und die Zahl beginnt. Verschiedene Locales platzieren Symbole an unterschiedlichen Positionen. Einige Locales verwenden unterschiedliche Trennzeichen. Das zuverlässige Parsen dieser Zeichenketten erfordert komplexe Logik, die die bereits in der Intl-API implementierten Formatierungsregeln dupliziert.
Betrachten Sie ein Dashboard, das Geldbeträge mit dem Währungssymbol in einer anderen Farbe anzeigt. Mit format() müssten Sie:
- Erkennen, welche Zeichen das Währungssymbol sind
- Leerzeichen zwischen Symbol und Zahl berücksichtigen
- Unterschiedliche Symbolpositionen über Locales hinweg handhaben
- Die Zeichenkette sorgfältig parsen, um die Zahl nicht zu beschädigen
Dieser Ansatz ist fragil und fehleranfällig. Jede Änderung an den Locale-Formatierungsregeln bricht Ihre Parsing-Logik.
Die Methode formatToParts() eliminiert dieses Problem, indem sie die Komponenten separat bereitstellt. Sie erhalten strukturierte Daten, die Ihnen unabhängig vom Locale genau sagen, welcher Teil welcher ist.
Verwendung von formatToParts zum Abrufen von Zahlenkomponenten
Die Methode formatToParts() funktioniert identisch zu format(), mit Ausnahme ihres Rückgabewerts. Sie erstellen einen Formatter mit denselben Optionen und rufen dann formatToParts() anstelle von format() auf.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
console.log(parts);
Dies gibt ein Array von Objekten aus:
[
{ type: "currency", value: "$" },
{ type: "integer", value: "1" },
{ type: "group", value: "," },
{ type: "integer", value: "234" },
{ type: "decimal", value: "." },
{ type: "fraction", value: "56" }
]
Jedes Objekt enthält eine Eigenschaft type, die identifiziert, was der Teil darstellt, und eine Eigenschaft value, die den tatsächlichen String enthält. Die Teile erscheinen in derselben Reihenfolge, wie sie in der formatierten Ausgabe vorkommen würden.
Sie können dies überprüfen, indem Sie alle Werte zusammenfügen:
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Output: "$1,234.56"
Die verketteten Teile erzeugen exakt dieselbe Ausgabe wie der Aufruf von format().
Verständnis der Teiltypen
Die Eigenschaft type identifiziert jede Komponente. Unterschiedliche Formatierungsoptionen erzeugen unterschiedliche Teiltypen.
Für grundlegende Zahlenformatierung:
const formatter = new Intl.NumberFormat("en-US");
const parts = formatter.formatToParts(1234.56);
console.log(parts);
// [
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
Der Typ integer repräsentiert den ganzzahligen Teil. Mehrere integer-Teile erscheinen, wenn Gruppentrennzeichen die Zahl aufteilen. Der Typ group repräsentiert das Tausendertrennzeichen. Der Typ decimal repräsentiert das Dezimaltrennzeichen. Der Typ fraction repräsentiert Ziffern nach dem Dezimaltrennzeichen.
Für Währungsformatierung:
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR"
});
const parts = formatter.formatToParts(1234.56);
console.log(parts);
// [
// { type: "currency", value: "€" },
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
Der Typ currency erscheint je nach Locale-Konventionen vor oder nach der Zahl.
Für Prozentangaben:
const formatter = new Intl.NumberFormat("en-US", {
style: "percent"
});
const parts = formatter.formatToParts(0.1234);
console.log(parts);
// [
// { type: "integer", value: "12" },
// { type: "percentSign", value: "%" }
// ]
Der Typ percentSign repräsentiert das Prozentzeichen.
Für kompakte Notation:
const formatter = new Intl.NumberFormat("en-US", {
notation: "compact"
});
const parts = formatter.formatToParts(1500000);
console.log(parts);
// [
// { type: "integer", value: "1" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "5" },
// { type: "compact", value: "M" }
// ]
Der Typ compact repräsentiert den Größenindikator wie K, M oder B.
Anwenden von benutzerdefiniertem Styling auf Zahlenteile
Der primäre Anwendungsfall für formatToParts() ist das Anwenden unterschiedlicher Styles auf verschiedene Komponenten. Sie können das Parts-Array verarbeiten, um bestimmte Typen in HTML-Elemente einzuschließen.
Das Währungssymbol fett darstellen:
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const parts = formatter.formatToParts(1234.56);
const html = parts
.map(part => {
if (part.type === "currency") {
return `<strong>${part.value}</strong>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "<strong>$</strong>1,234.56"
Dieser Ansatz funktioniert für jede Markup-Sprache. Sie können HTML, JSX oder jedes andere Format generieren, indem Sie das Parts-Array verarbeiten.
Dezimalstellen unterschiedlich stylen:
const formatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2
});
const parts = formatter.formatToParts(1234.5);
const html = parts
.map(part => {
if (part.type === "decimal" || part.type === "fraction") {
return `<span class="text-gray-500">${part.value}</span>`;
}
return part.value;
})
.join("");
console.log(html);
// Output: "1,234<span class="text-gray-500">.50</span>"
Dieses Muster ist in Preisdarstellungen üblich, bei denen der Dezimalteil kleiner oder heller erscheint.
Farbcodierung negativer Zahlen
Finanzanwendungen zeigen negative Zahlen oft in Rot an. Mit formatToParts() können Sie das Minuszeichen erkennen und entsprechend Styling anwenden.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatWithColor(number) {
const parts = formatter.formatToParts(number);
const hasMinusSign = parts.some(part => part.type === "minusSign");
const html = parts
.map(part => part.value)
.join("");
if (hasMinusSign) {
return `<span class="text-red-600">${html}</span>`;
}
return html;
}
console.log(formatWithColor(-1234.56));
// Output: "<span class="text-red-600">-$1,234.56</span>"
console.log(formatWithColor(1234.56));
// Output: "$1,234.56"
Dieser Ansatz erkennt negative Zahlen zuverlässig über alle Locales hinweg, selbst bei solchen, die unterschiedliche Symbole oder Positionen für Negativindikatoren verwenden.
Erstellen benutzerdefinierter Zahlenanzeigen mit mehreren Styles
Komplexe Interfaces kombinieren oft mehrere Styling-Regeln. Sie können gleichzeitig unterschiedliche Klassen oder Elemente auf verschiedene Part-Typen anwenden.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatCurrency(number) {
const parts = formatter.formatToParts(number);
return parts
.map(part => {
switch (part.type) {
case "currency":
return `<span class="currency-symbol">${part.value}</span>`;
case "integer":
return `<span class="integer">${part.value}</span>`;
case "group":
return `<span class="group">${part.value}</span>`;
case "decimal":
return `<span class="decimal">${part.value}</span>`;
case "fraction":
return `<span class="fraction">${part.value}</span>`;
case "minusSign":
return `<span class="minus">${part.value}</span>`;
default:
return part.value;
}
})
.join("");
}
console.log(formatCurrency(1234.56));
// Output: "<span class="currency-symbol">$</span><span class="integer">1</span><span class="group">,</span><span class="integer">234</span><span class="decimal">.</span><span class="fraction">56</span>"
Diese granulare Kontrolle ermöglicht präzises Styling für jede Komponente. Sie können dann CSS verwenden, um jede Klasse unterschiedlich zu stylen.
Alle verfügbaren Part-Typen
Die Property type kann abhängig von den verwendeten Formatierungsoptionen folgende Werte haben:
integer: Ganzzahlige Ziffernfraction: Dezimalzifferndecimal: Dezimaltrennzeichengroup: Tausendertrennzeichencurrency: Währungssymbolliteral: Leerzeichen oder anderer literaler Text, der durch Formatierung hinzugefügt wirdpercentSign: ProzentzeichenminusSign: Negativzahl-IndikatorplusSign: Positivzahl-Indikator (wennsignDisplaygesetzt ist)unit: Unit-String für Unit-Formatierungcompact: Größenindikator in kompakter Notation (K, M, B)exponentInteger: Exponentenwert in wissenschaftlicher NotationexponentMinusSign: Minuszeichen im ExponentenexponentSeparator: Symbol, das Mantisse vom Exponenten trenntinfinity: Unendlichkeitsdarstellungnan: Not-a-Number-Darstellungunknown: Nicht erkannte Tokens
Nicht jede Formatierungsoption erzeugt jeden Teiltyp. Die Teile, die Sie erhalten, hängen vom Zahlenwert und der Formatter-Konfiguration ab.
Wissenschaftliche Notation erzeugt exponentenbezogene Teile:
const formatter = new Intl.NumberFormat("en-US", {
notation: "scientific"
});
const parts = formatter.formatToParts(1234);
console.log(parts);
// [
// { type: "integer", value: "1" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "234" },
// { type: "exponentSeparator", value: "E" },
// { type: "exponentInteger", value: "3" }
// ]
Spezielle Werte erzeugen spezifische Teiltypen:
const formatter = new Intl.NumberFormat("en-US");
console.log(formatter.formatToParts(Infinity));
// [{ type: "infinity", value: "∞" }]
console.log(formatter.formatToParts(NaN));
// [{ type: "nan", value: "NaN" }]
Barrierefreie Zahlenanzeigen erstellen
Sie können formatToParts() verwenden, um formatierten Zahlen Barrierefreiheitsattribute hinzuzufügen. Dies hilft Screenreadern, Werte korrekt anzusagen.
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
function formatAccessibleCurrency(number) {
const parts = formatter.formatToParts(number);
const formatted = parts.map(part => part.value).join("");
return `<span aria-label="${number} US dollars">${formatted}</span>`;
}
console.log(formatAccessibleCurrency(1234.56));
// Output: "<span aria-label="1234.56 US dollars">$1,234.56</span>"
Dies stellt sicher, dass Screenreader sowohl den formatierten Anzeigewert als auch den zugrunde liegenden numerischen Wert mit entsprechendem Kontext ansagen.
Bestimmte Zahlenbereiche hervorheben
Einige Anwendungen heben Zahlen hervor, die in bestimmte Bereiche fallen. Mit formatToParts() können Sie Styling basierend auf dem Wert anwenden und dabei die korrekte Formatierung beibehalten.
const formatter = new Intl.NumberFormat("en-US");
function formatWithThreshold(number, threshold) {
const parts = formatter.formatToParts(number);
const formatted = parts.map(part => part.value).join("");
if (number >= threshold) {
return `<span class="text-green-600 font-bold">${formatted}</span>`;
}
return formatted;
}
console.log(formatWithThreshold(1500, 1000));
// Output: "<span class="text-green-600 font-bold">1,500</span>"
console.log(formatWithThreshold(500, 1000));
// Output: "500"
Die Zahl erhält die korrekte Formatierung für das Gebietsschema, während bedingtes Styling basierend auf der Geschäftslogik angewendet wird.
Wann formatToParts statt format verwenden
Verwenden Sie format(), wenn Sie einen einfachen formatierten String ohne Anpassungen benötigen. Dies ist der häufigste Fall für die meisten Zahlenanzeigen.
Verwenden Sie formatToParts(), wenn Sie:
- Unterschiedliches Styling auf verschiedene Teile der Zahl anwenden möchten
- HTML oder JSX mit formatierten Zahlen erstellen
- Attributen oder Metadaten zu bestimmten Komponenten hinzufügen
- Formatierte Zahlen in komplexe Layouts integrieren
- Formatierte Ausgaben programmatisch verarbeiten
Die Methode formatToParts() hat etwas mehr Overhead als format(), da sie ein Array von Objekten anstelle eines einzelnen Strings erstellt. Dieser Unterschied ist für typische Anwendungen vernachlässigbar, aber wenn Sie Tausende von Zahlen pro Sekunde formatieren, bietet format() eine bessere Performance.
Für die meisten Anwendungen sollten Sie basierend auf Ihren Styling-Anforderungen und nicht auf Performance-Überlegungen wählen. Wenn Sie die Ausgabe nicht anpassen müssen, verwenden Sie format(). Wenn Sie benutzerdefiniertes Styling oder Markup benötigen, verwenden Sie formatToParts().
Wie Parts die gebietsspezifische Formatierung beibehalten
Das Parts-Array behält automatisch gebietsspezifische Formatierungsregeln bei. Verschiedene Gebietsschemas platzieren Symbole an unterschiedlichen Positionen und verwenden unterschiedliche Trennzeichen, aber formatToParts() behandelt diese Unterschiede.
const usdFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
console.log(usdFormatter.formatToParts(1234.56));
// [
// { type: "currency", value: "$" },
// { type: "integer", value: "1" },
// { type: "group", value: "," },
// { type: "integer", value: "234" },
// { type: "decimal", value: "." },
// { type: "fraction", value: "56" }
// ]
const eurFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR"
});
console.log(eurFormatter.formatToParts(1234.56));
// [
// { type: "integer", value: "1" },
// { type: "group", value: "." },
// { type: "integer", value: "234" },
// { type: "decimal", value: "," },
// { type: "fraction", value: "56" },
// { type: "literal", value: " " },
// { type: "currency", value: "€" }
// ]
Die deutsche Formatierung platziert die Währung nach der Zahl mit einem Leerzeichen. Das Tausendertrennzeichen ist ein Punkt und das Dezimaltrennzeichen ist ein Komma. Ihr Styling-Code verarbeitet das Parts-Array unabhängig vom Gebietsschema auf die gleiche Weise, und die Formatierung passt sich automatisch an.
Der Typ literal repräsentiert alle Abstände oder Texte, die vom Formatter eingefügt werden und nicht in andere Kategorien passen. Bei der deutschen Währungsformatierung repräsentiert er das Leerzeichen zwischen der Zahl und dem Währungssymbol.
Kombination von formatToParts mit Framework-Komponenten
Moderne Frameworks wie React können formatToParts() verwenden, um Komponenten effizient zu erstellen.
function CurrencyDisplay({ value, locale, currency }) {
const formatter = new Intl.NumberFormat(locale, {
style: "currency",
currency: currency
});
const parts = formatter.formatToParts(value);
return (
<span className="currency-display">
{parts.map((part, index) => {
if (part.type === "currency") {
return <strong key={index}>{part.value}</strong>;
}
if (part.type === "fraction" || part.type === "decimal") {
return <span key={index} className="text-sm text-gray-500">{part.value}</span>;
}
return <span key={index}>{part.value}</span>;
})}
</span>
);
}
Diese Komponente wendet unterschiedliches Styling auf verschiedene Parts an und behält dabei die korrekte Formatierung für jedes Gebietsschema und jede Währung bei.