javascript - Vue3 Cleave js não funciona se não usar v-model.lazy
Atualmente, tento usar cleavejs para formatar o separador de milhares do meu número de entrada, ele mostra um comportamento estranho quando digito 1000.123, ele mostra 1.000,12, o que é o formato correto, mas o valor do meu v-model é 1000.123, não 1000.12. Outras pessoas sugerem usar v-model.lazy, mas ele só atualiza quando eu saio do foco do campo de texto.
Existe alguma outra maneira de resolver esse problema sem usar v-model.lazy?
Este é o meu componente atual
<script setup lang="ts">
import { ref, watch } from 'vue'
const props = withDefaults(defineProps<Props>(), {
type: 'text',
required: false,
readonly: false,
disabled: false
})
const inputValue = ref(props.modelValue)
const emit = defineEmits<{
(e: 'update:modelValue', value: string | number): void
}>()
watch(
() => props.modelValue,
() => {
inputValue.value = numeric.format(props.modelValue)
},
{
immediate: true
}
)
watch(
inputValue,
() => {
emit('update:modelValue', parseFloat(inputValue.value.toString().replace(/(\d+),(?=\d+(\D|$))/g, '$1')))
},
{
immediate: true
}
)
</script>
<template>
<input
class="form-input"
v-model.lazy="inputValue"
v-cleave="{ numeral: true, numeralThousandsGroupStyle: 'thousand' }"
:placeholder="props.placeholder"
:required="props.required"
:readonly="props.readonly"
:disabled="props.disabled"
/>
</template>
Espero que o v-model retorne o mesmo valor que o cleavejs dava sem usar .lazy
Resposta #1
Primeiro, você não precisa usar watch de forma alguma, e não vamos emitir neste setter porque esperamos o evento do Cleavejs
const inputValue = computed({
set: (text: string) => {},
get: () => new Intl.NumberFormat('en-US').format(props.modelValue)
})
Em segundo lugar, emita dados de valor bruto do evento onValueChanged do Cleavejs
const emit = defineEmits<{
(e: 'update:modelValue', value: number): void
}>()
const onValueChanged = (e: any) => {
emit('update:modelValue', Number(e.target.rawValue))
}
Por último, atualize sua diretiva de entrada
v-cleave="{ numeral: true, numeralThousandsGroupStyle: 'thousand', onValueChanged: onValueChanged }"
Exemplo de Componente Completo
<script setup lang="ts">
import { computed } from 'vue'
export interface Props {
modelValue: number
}
const props = withDefaults(defineProps<Props>(), {})
const inputValue = computed({
set: (text: string) => {},
get: () => new Intl.NumberFormat('en-US').format(props.modelValue)
})
const emit = defineEmits<{
(e: 'update:modelValue', value: number): void
}>()
const onValueChanged = (e: any) => {
emit('update:modelValue', Number(e.target.rawValue))
}
</script>
<template>
<input
v-cleave="{ numeral: true, numeralThousandsGroupStyle: 'thousand', onValueChanged: onValueChanged }"
v-model="inputValue"
/>
</template>
