網站搜尋

javascript - 如果不使用 v-model.lazy,Vue3 的 Cleave js 無法運作


目前我嘗試使用 CleaveJS 來格式化千分位分隔我的輸入數字,當我輸入 1000.123 時,它顯示 1,000.12,這是正確的格式,但我的 v-model 值是 1000.123 而不是 1000.12。其他人建議使用 v-model.lazy,但它只有在我離開輸入框時才會更新。

有沒有其他方法可以解決這個問題,而不使用 v-model.lazy?

這是我目前的組件

<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>

我期望 v-model 返回與未使用 .lazy 的 cleavejs 相同的值

答案#1

首先,你根本不需要使用 watch,而且我們不會在這個 setter 上發出事件,因為我們等待 Cleavejs 事件

const inputValue = computed({
  set: (text: string) => {},
  get: () => new Intl.NumberFormat('en-US').format(props.modelValue)
})

其次,在 Cleavejs 的 onValueChanged 事件中發出原始值數據

const emit = defineEmits<{
  (e: 'update:modelValue', value: number): void
}>()

const onValueChanged = (e: any) => {
  emit('update:modelValue', Number(e.target.rawValue))
}

最後,更新您的輸入指令

v-cleave="{ numeral: true, numeralThousandsGroupStyle: 'thousand', onValueChanged: onValueChanged }"

完整元件範例

<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>