Wie man einzelne Teile formatierter Zahlen für benutzerdefinierte Anzeigen erhält
Formatierte Zahlen in Komponenten zerlegen, um benutzerdefinierte Formatierungen anzuwenden und komplexe Benutzeroberflächen zu erstellen
Einführung
Die Methode format() gibt eine vollständig formatierte Zeichenfolge wie "$1,234.56" oder "1.5M" zurück. Dies funktioniert gut für einfache Anzeigen, aber Sie können einzelne Teile nicht unterschiedlich gestalten. Sie können das Währungssymbol nicht fett formatieren, den Dezimalteil nicht anders einfärben oder benutzerdefinierte Markierungen auf bestimmte Komponenten anwenden.
JavaScript bietet die Methode formatToParts(), um dieses Problem zu lösen. Anstatt eine einzelne Zeichenfolge zurückzugeben, gibt sie ein Array von Objekten zurück, wobei jedes einen Teil der formatierten Zahl darstellt. Jeder Teil hat einen Typ wie currency, integer oder decimal und einen Wert wie $, 1234 oder .. Sie können diese Teile dann verarbeiten, um benutzerdefinierte Formatierungen anzuwenden, komplexe Layouts zu erstellen oder formatierte Zahlen in umfangreiche Benutzeroberflächen zu integrieren.
Warum formatierte Zeichenketten schwer anzupassen sind
Wenn Sie eine formatierte Zeichenfolge wie "$1,234.56" erhalten, können Sie nicht leicht erkennen, wo das Währungssymbol endet und die Zahl beginnt. Verschiedene Gebietsschemas platzieren Symbole an unterschiedlichen Positionen. Einige Gebietsschemas verwenden unterschiedliche Trennzeichen. Das zuverlässige Parsen dieser Zeichenketten erfordert komplexe Logik, die die bereits in der Intl-API implementierten Formatierungsregeln dupliziert.
Stellen Sie sich ein Dashboard vor, 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 dem Symbol und der Zahl berücksichtigen
- Unterschiedliche Symbolpositionen in verschiedenen Gebietsschemas behandeln
- Die Zeichenfolge sorgfältig parsen, um die Zahl nicht zu beschädigen
Dieser Ansatz ist fehleranfällig und störungsempfindlich. Jede Änderung an den Formatierungsregeln des Gebietsschemas beeinträchtigt Ihre Parsing-Logik.
Die Methode formatToParts() beseitigt dieses Problem, indem sie die Komponenten separat bereitstellt. Sie erhalten strukturierte Daten, die Ihnen genau mitteilen, welcher Teil welcher ist, unabhängig vom Gebietsschema.
Verwendung von formatToParts zum Abrufen von Zahlenkomponenten
Die Methode formatToParts() funktioniert identisch zu format(), mit Ausnahme des Rückgabewerts. Sie erstellen einen Formatierer 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 type-Eigenschaft, die angibt, was der Teil darstellt, und eine value-Eigenschaft, die die tatsächliche Zeichenfolge enthält. Die Teile erscheinen in derselben Reihenfolge wie in der formatierten Ausgabe.
Sie können dies überprüfen, indem Sie alle Werte zusammenfügen:
const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Ausgabe: "$1,234.56"
Die verketteten Teile erzeugen genau dieselbe Ausgabe wie der Aufruf von format().
Verständnis der Teiltypen
Die Eigenschaft type identifiziert jede Komponente. Verschiedene Formatierungsoptionen erzeugen unterschiedliche Teiltypen.
Für die 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 der Zahl. Mehrere integer-Teile erscheinen, wenn Gruppenseparatoren die Zahl aufteilen. Der Typ group repräsentiert den Tausendertrennzeichen. Der Typ decimal repräsentiert den Dezimalpunkt. Der Typ fraction repräsentiert die Ziffern nach dem Dezimalpunkt.
Für die 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 vor oder nach der Zahl, abhängig von den lokalen Konventionen.
Für Prozentsätze:
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.
Anwendung benutzerdefinierter Formatierung auf Zahlenteile
Der primäre Anwendungsfall für formatToParts() ist die Anwendung verschiedener Stile auf unterschiedliche Komponenten. Sie können das Parts-Array verarbeiten, um bestimmte Typen in HTML-Elemente einzuschließen.
Das Währungssymbol fett formatieren:
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 Auszeichnungssprache. Sie können HTML, JSX oder jedes andere Format generieren, indem Sie das Parts-Array verarbeiten.
Dezimalstellen anders formatieren:
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 üblich bei Preisanzeigen, bei denen der Dezimalteil kleiner oder heller erscheint.
Farbliche Kennzeichnung negativer Zahlen
Finanzanwendungen stellen negative Zahlen oft in rot dar. Mit formatToParts() können Sie das Minuszeichen erkennen und entsprechende Formatierungen 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 in allen Locales, selbst in solchen, die unterschiedliche Symbole oder Positionen für negative Indikatoren verwenden.
Benutzerdefinierte Zahlenanzeigen mit mehreren Stilen erstellen
Komplexe Benutzeroberflächen kombinieren oft mehrere Stilregeln. Sie können verschiedene Klassen oder Elemente gleichzeitig auf verschiedene Teiltypen 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 eine präzise Gestaltung jeder Komponente. Sie können dann CSS verwenden, um jede Klasse unterschiedlich zu gestalten.
Alle verfügbaren Teiltypen
Die Eigenschaft type kann je nach verwendeten Formatierungsoptionen folgende Werte haben:
integer: Ziffern der ganzen Zahlfraction: Dezimalzifferndecimal: Dezimaltrennzeichengroup: Tausendertrennzeichencurrency: Währungssymbolliteral: Leerzeichen oder anderer Literaltext, der durch Formatierung hinzugefügt wirdpercentSign: ProzentzeichenminusSign: NegativzahlenindikatorplusSign: Positivzahlenindikator (wennsignDisplaygesetzt ist)unit: Einheitsstring für Einheitenformatierungcompact: Größenindikator in kompakter Notation (K, M, B)exponentInteger: Exponentwert in wissenschaftlicher NotationexponentMinusSign: Minuszeichen im ExponentenexponentSeparator: Symbol, das Mantisse vom Exponenten trenntinfinity: Unendlichkeitsdarstellungnan: Not-a-number-Darstellungunknown: Nicht erkannte Token
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" }]
Erstellung barrierefreier Zahlenanzeigen
Sie können formatToParts() verwenden, um Barrierefreiheitsattribute zu formatierten Zahlen hinzuzufügen. Dies hilft Screenreadern, Werte korrekt anzukündigen.
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 zugrundeliegenden numerischen Wert mit dem richtigen Kontext ankündigen.
Hervorhebung bestimmter Zahlenbereiche
Einige Anwendungen heben Zahlen hervor, die in bestimmte Bereiche fallen. Mit formatToParts() können Sie Styling basierend auf dem Wert anwenden, während die korrekte Formatierung beibehalten wird.
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 das bedingte Styling basierend auf der Geschäftslogik angewendet wird.
Wann formatToParts versus format verwenden
Verwenden Sie format(), wenn Sie eine einfache formatierte Zeichenfolge ohne Anpassungen benötigen. Dies ist der häufigste Fall für die meisten Zahlenanzeigen.
Verwenden Sie formatToParts(), wenn Sie Folgendes benötigen:
- Anwendung verschiedener Stile auf verschiedene Teile der Zahl
- Erstellung von HTML oder JSX mit formatierten Zahlen
- Hinzufügen von Attributen oder Metadaten zu bestimmten Komponenten
- Integration formatierter Zahlen in komplexe Layouts
- Programmatische Verarbeitung formatierter Ausgaben
Die Methode formatToParts() hat einen etwas höheren Overhead als format(), da sie ein Array von Objekten anstelle einer einzelnen Zeichenfolge erstellt. Dieser Unterschied ist für typische Anwendungen vernachlässigbar, aber wenn Sie Tausende von Zahlen pro Sekunde formatieren, bietet format() eine bessere Leistung.
Für die meisten Anwendungen sollten Sie die Wahl eher auf Basis Ihrer Styling-Anforderungen als auf Leistungsbedenken treffen. Wenn Sie die Ausgabe nicht anpassen müssen, verwenden Sie format(). Wenn Sie benutzerdefiniertes Styling oder Markup benötigen, verwenden Sie formatToParts().
Wie Teile die sprachspezifische Formatierung bewahren
Das parts-Array behält automatisch die sprachspezifischen Formatierungsregeln bei. Verschiedene Spracheinstellungen 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 Gruppierungszeichen ist ein Punkt und das Dezimaltrennzeichen ist ein Komma. Ihr Styling-Code verarbeitet das parts-Array auf die gleiche Weise unabhängig von der Spracheinstellung, und die Formatierung passt sich automatisch an.
Der Typ literal repräsentiert jegliche Leerzeichen oder Text, die vom Formatierer 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() nutzen, 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 unterschiedliche Stile auf verschiedene Teile an, während die korrekte Formatierung für jede Spracheinstellung und Währung beibehalten wird.