Лучший способ интеграции BigNumber.js во Vue проект
Как можно реализовать интеграцию BigNumber.js в проект для использования в формах?
Вариант 1: Можно использовать computed геттеры и сеттеры, где в сеттерах оборачивать value в BigNumber:
// template
<input v-model="fieldValue" />
// computed
computed: {
fieldValue: {
get() { return this.form.count.toString() },
set(v) { this.form.count = new BigNumber(v) }
}
}
Минус первого варианта в том, что под каждое поле нужно делать computed свойство с геттерами и сеттерами.
Вариант 2 Компонент обертка, который бы инкапсулировал конвертацию обычного числового типа в bigNubmer и наоборот. Минус: Необходимость пробрасывать пропсы и слоты через обертку в кастомный компонент. (Конкретно в моем случае я использую сторонний компонент)
Вариант 3
Использовать @change событие и :value атрибут у компонента input вместо v-model. Т.е. в обработчике change оборачивать введенное число в BigNumber и в value получать его значение.
минус: не используем v-model, что, как по мне, куда лаконичнее
Вариант 4 Кастомная директива по типу v-model? v-big-number, например
Какие еще решения можете предложить? Заранее спасибо!
ссылка на либу https://github.com/MikeMcl/bignumber.js
Ответы (1 шт):
2 и 4 вариант звучат хорошо, но я бы все же пердпочел второй вариант.
Хотя деректива и заманчива, но вам по факту придется реализовывать чуть ли не свой собственный v-model, что со всеми пограничными случаями не такая тревиальная задача как может показаться.
Что касается минусов второго варианта, пропсы пробросить не сложно, слотов у Вас вряд ли наберется даже десяток, из плюсов — Вы инкапсулируете логику в одном месте.
Ниже практически полный пример, Вам нужно лишь настроить его под свои нужды.
<template>
<SomeUILibraryInput
v-bind="$attrs"
v-on="listeners"
v-model="model"
:class="className"
:style="componentStyles"
>
<slot />
</SomeUILibraryInput>
</template>
<script>
import SomeUILibraryInput from "./SomeUILibraryInput.vue";
import {
BigNumber
} from "bignumber.js";
export default {
name: "BigNumberInput",
components: {
SomeUILibraryInput,
},
props: {
value: {
type: null,
default: null,
},
className: {
type: [String, Array, Object],
default: null,
},
componentStyles: {
type: [String, Array, Object],
default: null,
},
},
computed: {
model: {
get() {
return this.value.toString();
},
set(value) {
this.$emit("input", new BigNumber(value || 0));
},
},
listeners() {
const {
input,
...other
} = this.$listeners;
return other;
},
},
};
</script>
<style></style>