Wie formatiere ich Währungen in einer Vue-Komponente?

81

Meine Vue-Komponente sieht folgendermaßen aus:

<template>
    <div>
        <div class="panel-group"v-for="item in list">
            <div class="col-md-8">
                <small>
                   Total: <b>{{ item.total }}</b>
                </small>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        ...
        computed: {
            list: function() {
                return this.$store.state.transaction.list
            },
            ...
        }
    }
</script>

Das Ergebnis von {{ item.total }}ist

26000000

Aber ich möchte, dass es so formatiert wird:

26.000.000,00

In jquery oder javascript kann ich es tun

Aber wie geht das in der Vue-Komponente?

samuel toh
quelle
1
Wenn Sie es in Javascript tun können, können Sie es in Vue tun ... verwenden Sie berechnete Eigenschaften und geben Sie den Javascript-Code zurück.
Happyriwan

Antworten:

82

UPDATE: Ich schlage vor, eine Lösung mit Filtern zu verwenden, die von @Jess bereitgestellt wird.

Ich würde eine Methode dafür schreiben, und wo Sie dann den Preis formatieren müssen, können Sie die Methode einfach in die Vorlage einfügen und den Wert weitergeben

methods: {
    formatPrice(value) {
        let val = (value/1).toFixed(2).replace('.', ',')
        return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".")
    }
}

Und dann in Vorlage:

<template>
    <div>
        <div class="panel-group"v-for="item in list">
            <div class="col-md-8">
                <small>
                   Total: <b>{{ formatPrice(item.total) }}</b>
                </small>
            </div>
        </div>
    </div>
</template>

Übrigens - ich habe nicht zu viel Wert auf Ersetzen und regulären Ausdruck gelegt. Es könnte verbessert werden.enter code here

Belmin Bedak
quelle
11
Siehe auch developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… für die integrierte Formatierung lokaler Währungen.
Roy J
@RoyJ Guter Fang. Ich habe gerade Regex aus einem früheren Projekt kopiert, im Grunde konnte er den Wert der Methode zurückgeben, wie er wollte.
Belmin Bedak
@BelminBedak was denkst du return (value/1).toFixed(2).toLocalString();?
Retrovertigo
Funktioniert, ersetzt aber alle Dezimalstellen durch Kommas
Dylan Glockler
Warum nicht computedstattdessen verwenden?
localhost
182

Ich habe einen Filter erstellt. Der Filter kann auf jeder Seite verwendet werden.

Vue.filter('toCurrency', function (value) {
    if (typeof value !== "number") {
        return value;
    }
    var formatter = new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 0
    });
    return formatter.format(value);
});

Dann kann ich diesen Filter folgendermaßen verwenden:

        <td class="text-right">
            {{ invoice.fees | toCurrency }}
        </td>

Ich habe diese verwandten Antworten verwendet, um bei der Implementierung des Filters zu helfen:

Jess
quelle
5
Mein Mann! Ich wusste nicht einmal, dass du das kannst. Dank hat mein Währungsproblem gelöst und meine Mixins aufgeräumt, da die meisten von ihnen solche Sachen machten.
Ominus
1
Dies ist die richtige Antwort
ierdna
Das Intlhat nicht die beste Unterstützung .
Злья Зеленько
1
Wie wäre es isNaN(parseFloat(value))eher als typeof value !== "number"?
RonnyKnoxville
@ JackalopeZero: Ja, das ist eine bessere Überprüfung. Hat in meinem Fall funktioniert.
dotNET
22

Mit vuejs 2 können Sie vue2-Filter verwenden, die auch andere Extras enthalten.

npm install vue2-filters


import Vue from 'vue'
import Vue2Filters from 'vue2-filters'

Vue.use(Vue2Filters)

Dann benutze es so:

{{ amount | currency }} // 12345 => $12,345.00

Ref: https://www.npmjs.com/package/vue2-filters

Yao Liu
quelle
10

Sie können die Währung so formatieren, dass Sie Ihren eigenen Code schreiben. Dies ist jedoch nur eine Lösung für den Moment. Wenn Ihre App wächst, benötigen Sie möglicherweise andere Währungen.

Es gibt noch ein anderes Problem:

  1. Für EN-us - das Dolarzeichen steht immer vor der Währung - 2,00 USD,
  2. Für den ausgewählten PL geben Sie ein Zeichen nach einem Betrag von 2,00 zł zurück.

Ich denke, die beste Option ist die Verwendung einer komplexen Lösung für die Internationalisierung, z. B. Bibliothek vue-i18n ( http://kazupon.github.io/vue-i18n/ ).

Ich benutze dieses Plugin und muss mich nicht um solche Dinge kümmern. Bitte schauen Sie sich die Dokumentation an - es ist wirklich einfach:

http://kazupon.github.io/vue-i18n/guide/number.html

Sie verwenden also einfach:

<div id="app">
  <p>{{ $n(100, 'currency') }}</p>
</div>

und setzen Sie EN-us, um $ 100.00 zu erhalten :

<div id="app">
  <p>$100.00</p>
</div>

oder PL einstellen, um 100,00 zł zu erhalten :

<div id="app">
  <p>100,00 zł</p>
</div>

Dieses Plugin bietet auch verschiedene Funktionen wie Übersetzungen und Datumsformatierung.

Arkowsky
quelle
8

Der Kommentar von @RoyJ hat einen tollen Vorschlag. In der Vorlage können Sie nur integrierte lokalisierte Zeichenfolgen verwenden:

<small>
     Total: <b>{{ item.total.toLocaleString() }}</b>
</small>

Es wird in einigen älteren Browsern nicht unterstützt, aber wenn Sie auf IE 11 und höher abzielen, sollte es Ihnen gut gehen.

AaronBaker
quelle
Einfach so. Bestätigt, dass es funktioniert. Fühlen Sie sich wie es sollte die ausgewählte Antwort sein!
UX Andre
4

Ich habe die von @Jess vorgeschlagene benutzerdefinierte Filterlösung verwendet, aber in meinem Projekt verwenden wir Vue zusammen mit TypeScript. So sieht es mit TypeScript und Klassendekoratoren aus:

import Component from 'vue-class-component';
import { Filter } from 'vue-class-decorator';

@Component
export default class Home extends Vue {

  @Filter('toCurrency')
  private toCurrency(value: number): string {
    if (isNaN(value)) {
        return '';
    }

    var formatter = new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 0
    });
    return formatter.format(value);
  }
}

In diesem Beispiel kann der Filter nur innerhalb der Komponente verwendet werden. Ich habe noch nicht versucht, es als globalen Filter zu implementieren.

Andreas Bauer
quelle
2

Sie können dieses Beispiel verwenden

formatPrice(value) {
  return value.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
},
Mehrab Esmailnia
quelle
1

Es gibt Probleme mit der Genauigkeit der akzeptierten Antwort.

Die Rundungsfunktion (Wert, Dezimalstellen) in diesem Test funktioniert. im Gegensatz zu dem einfachen toFixed-Beispiel.

Dies ist ein Test der Methode toFixed vs round.

http://www.jacklmoore.com/notes/rounding-in-javascript/

  Number.prototype.format = function(n) {
      return this.toFixed(Math.max(0, ~~n));
  };
  function round(value, decimals) {
    return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
  }

  // can anyone tell me why these are equivalent for  50.005, and 1050.005 through 8150.005 (increments of 50)

  var round_to = 2;
  var maxInt = 1500000;
  var equalRound = '<h1>BEGIN HERE</h1><div class="matches">';
  var increment = 50;
  var round_from = 0.005;
  var expected = 0.01;
  var lastWasMatch = true;

  for( var n = 0; n < maxInt; n=n+increment){
    var data = {};
    var numberCheck = parseFloat(n + round_from);
    data.original = numberCheck * 1;
    data.expected =  Number(n + expected) * 1;
    data.formatIt = Number(numberCheck).format(round_to) * 1;
    data.roundIt = round(numberCheck, round_to).toFixed(round_to) * 1;
    data.numberIt = Number(numberCheck).toFixed(round_to) * 1;
    //console.log(data);

    if( data.roundIt !== data.formatIt || data.formatIt !== data.numberIt ||
       data.roundIt !== data.numberIt || data.roundIt != data.expected
      ){
        if(lastWasMatch){
          equalRound = equalRound + '</div><div class="errors"> <hr/> Did Not Round UP <hr/>' ;
            document.write(' <h3>EXAMPLE: Did Not Round UP: ' + numberCheck + '</h3><br /><hr/> ');
            document.write('expected: '+data.expected + ' :: ' + (typeof data.expected)  + '<br />');
            document.write('format: '+data.formatIt + ' :: ' + (typeof data.formatIt)  + '<br />');
            document.write('round : '+data.roundIt + ' :: ' + (typeof data.roundIt)  + '<br />');
            document.write('number: '+data.numberIt + ' :: ' + (typeof data.numberIt)  + '<br />');
            lastWasMatch=false;
        }
        equalRound = equalRound + ', ' + numberCheck;
    } else {
        if(!lastWasMatch){
          equalRound = equalRound + '</div><div class="matches"> <hr/> All Rounded UP! <hr/>' ;
        } {
            lastWasMatch=true;
        }
        equalRound = equalRound + ', ' + numberCheck;
    }
  }
  document.write('equalRound: '+equalRound + '</div><br />');

Mixin Beispiel

  export default {
    methods: {
      roundFormat: function (value, decimals) {
        return Number(Math.round(value+'e'+decimals)+'e-'+decimals).toFixed(decimals);
      },
      currencyFormat: function (value, decimals, symbol='$') {
        return symbol + this.roundFormat(value,2);
      }
    }
  }

Artistan
quelle
1
Sie könnten val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".")danach noch für die verwenden. und Änderungen.
Artistan