InputNumber

一个用于输入数值并可自定义范围的输入组件。

用法

使用 v-model 指令来控制 InputNumber 的值。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" />
</template>

使用 default-value prop 在您不需要控制其状态时设置初始值。

<template>
  <UInputNumber :default-value="5" />
</template>
此组件依赖于@internationalized/number包,它提供了跨语言环境和数字系统格式化和解析数字的实用工具。

最小值/最大值

使用 minmax prop 设置 InputNumber 的最小值和最大值。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" :min="0" :max="10" />
</template>

步进

使用 step prop 设置 InputNumber 的步进值。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" :step="2" />
</template>

Orientation

使用 orientation prop 更改 InputNumber 的方向。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" orientation="vertical" />
</template>

占位符

使用 placeholder 属性设置占位文本。

<template>
  <UInputNumber placeholder="Enter a number" />
</template>

颜色

使用 color prop 更改 InputNumber 获得焦点时的环形颜色。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" color="neutral" highlight />
</template>

变体

使用 variant prop 更改 InputNumber 的变体。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" variant="subtle" color="neutral" />
</template>

尺寸

使用 size prop 更改 InputNumber 的大小。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" size="xl" />
</template>

禁用

使用 disabled prop 禁用 InputNumber。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value" disabled />
</template>

递增/递减

使用 incrementdecrement prop 通过任何 Button prop 自定义递增和递减按钮。默认为 { variant: 'link' }

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber
    v-model="value"
    :increment="{
      color: 'neutral',
      variant: 'solid',
      size: 'xs'
    }"
    :decrement="{
      color: 'neutral',
      variant: 'solid',
      size: 'xs'
    }"
  />
</template>

递增/递减图标

使用 increment-icondecrement-icon prop 自定义按钮 Icon。默认为 i-lucide-plus / i-lucide-minus

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber
    v-model="value"
    increment-icon="i-lucide-arrow-right"
    decrement-icon="i-lucide-arrow-left"
  />
</template>

示例

带小数格式

使用 format-options prop 自定义值的格式。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber
    v-model="value"
    :format-options="{
      signDisplay: 'exceptZero',
      minimumFractionDigits: 1
    }"
  />
</template>

带百分比格式

使用 format-options prop 配合 style: 'percent' 自定义值的格式。

<script setup lang="ts">
const value = ref(0.05)
</script>

<template>
  <UInputNumber
    v-model="value"
    :step="0.01"
    :format-options="{
      style: 'percent'
    }"
  />
</template>

带货币格式

使用 format-options prop 配合 style: 'currency' 自定义值的格式。

<script setup lang="ts">
const value = ref(1500)
</script>

<template>
  <UInputNumber
    v-model="value"
    :format-options="{
      style: 'currency',
      currency: 'EUR',
      currencyDisplay: 'code',
      currencySign: 'accounting'
    }"
  />
</template>

无按钮

您可以使用 incrementdecrement prop 控制按钮的可见性。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber
    v-model="value"
    :increment="false"
    :decrement="false"
  />
</template>

在 FormField 中

您可以在 FormField 组件中使用 InputNumber 以显示标签、帮助文本、必填指示器等。

指定尝试次数
<script setup lang="ts">
const retries = ref(0)
</script>

<template>
  <UFormField label="Retries" help="Specify number of attempts" required>
    <UInputNumber v-model="retries" placeholder="Enter retries" />
  </UFormField>
</template>

使用插槽

使用 #increment#decrement slot 自定义按钮。

<script setup lang="ts">
const value = ref(5)
</script>

<template>
  <UInputNumber v-model="value">
    <template #decrement>
      <UButton size="xs" icon="i-lucide-minus" />
    </template>

    <template #increment>
      <UButton size="xs" icon="i-lucide-plus" />
    </template>
  </UInputNumber>
</template>

API

属性

属性默认值类型
as

'div'

any

此组件应渲染为的元素或组件。

placeholder

string

输入为空时的占位文本。

color

'主要'

"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"

variant

'outline'

"soft" | "outline" | "subtle" | "ghost" | "none"

尺寸

'md'

"sm" | "md" | "xs" | "lg" | "xl"

高亮

boolean

高亮环形颜色,如同焦点状态。

orientation

'horizontal'

"horizontal" | "vertical"

输入菜单的方向。

递增

true

配置递增按钮。colorsize 是继承的。

递增图标

appConfig.ui.icons.plus

字符串 | 对象

递增值时显示的图标。

禁用递增

boolean

禁用递增按钮。

递减

true

boolean | ButtonProps

配置递减按钮。colorsize 是继承的。

递减图标

appConfig.ui.icons.minus

字符串 | 对象

递减值时显示的图标。

禁用递减

boolean

禁用递减按钮。

autofocus

boolean

autofocusDelay

number

modelModifiers

Pick<ModelModifiers, "optional">

语言环境

UApp.locale.code

string

用于数字格式化和解析的语言环境。

disabled

boolean

当为 true 时,阻止用户与数字输入框交互。

name

string

字段的名称。作为名称/值对的一部分随其所属表单提交。

modelValue

null | number

defaultValue

number

required

boolean

当为 true 时,表示用户必须在提交所属表单之前设置值。

id

string

元素的 ID

最小值

number

输入允许的最小值。

max

number

输入允许的最大值。

步进

number

输入值在每次递增或递减“滴答”时改变的数量。

步进捕捉

boolean

当为 false 时,阻止值捕捉到最接近的步进值增量。

格式选项

Intl.NumberFormatOptions

数字字段中显示值的格式选项。这也会影响用户允许输入的字符。

禁用滚轮更改

boolean

当为 true 时,阻止值在滚轮滚动时改变。

反转滚轮更改

boolean

当为 true 时,反转滚轮更改的方向。

只读

boolean

当为 true 时,数字输入框为只读。

ui

{ root?: ClassNameValue; base?: ClassNameValue; increment?: ClassNameValue; decrement?: ClassNameValue; }

插槽

插槽类型
递增

{}

递减

{}

事件

事件类型
change

[event: Event]

blur

[event: FocusEvent]

update:modelValue

[value: number]

可访问属性

通过模板引用访问组件时,您可以使用以下内容:

名称类型
inputRefRef<InstanceType<typeof NumberFieldInput> | null>

主题

app.config.ts
export default defineAppConfig({
  ui: {
    inputNumber: {
      slots: {
        root: 'relative inline-flex items-center',
        base: [
          'w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75',
          'transition-colors'
        ],
        increment: 'absolute flex items-center',
        decrement: 'absolute flex items-center'
      },
      variants: {
        fieldGroup: {
          horizontal: {
            root: 'group has-focus-visible:z-[1]',
            base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
          },
          vertical: {
            root: 'group has-focus-visible:z-[1]',
            base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
          }
        },
        color: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        size: {
          xs: 'px-2 py-1 text-xs gap-1',
          sm: 'px-2.5 py-1.5 text-xs gap-1.5',
          md: 'px-2.5 py-1.5 text-sm gap-1.5',
          lg: 'px-3 py-2 text-sm gap-2',
          xl: 'px-3 py-2 text-base gap-2'
        },
        variant: {
          outline: 'text-highlighted bg-default ring ring-inset ring-accented',
          soft: 'text-highlighted bg-elevated/50 hover:bg-elevated focus:bg-elevated disabled:bg-elevated/50',
          subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
          ghost: 'text-highlighted bg-transparent hover:bg-elevated focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
          none: 'text-highlighted bg-transparent'
        },
        disabled: {
          true: {
            increment: 'opacity-75 cursor-not-allowed',
            decrement: 'opacity-75 cursor-not-allowed'
          }
        },
        orientation: {
          horizontal: {
            base: 'text-center',
            increment: 'inset-y-0 end-0 pe-1',
            decrement: 'inset-y-0 start-0 ps-1'
          },
          vertical: {
            increment: 'top-0 end-0 pe-1 [&>button]:py-0 scale-80',
            decrement: 'bottom-0 end-0 pe-1 [&>button]:py-0 scale-80'
          }
        },
        highlight: {
          true: ''
        },
        increment: {
          false: ''
        },
        decrement: {
          false: ''
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary'
        },
        {
          color: 'primary',
          highlight: true,
          class: 'ring ring-inset ring-primary'
        },
        {
          color: 'neutral',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-inverted'
        },
        {
          color: 'neutral',
          highlight: true,
          class: 'ring ring-inset ring-inverted'
        },
        {
          orientation: 'horizontal',
          decrement: false,
          class: 'text-start'
        },
        {
          decrement: true,
          size: 'xs',
          class: 'ps-7'
        },
        {
          decrement: true,
          size: 'sm',
          class: 'ps-8'
        },
        {
          decrement: true,
          size: 'md',
          class: 'ps-9'
        },
        {
          decrement: true,
          size: 'lg',
          class: 'ps-10'
        },
        {
          decrement: true,
          size: 'xl',
          class: 'ps-11'
        },
        {
          increment: true,
          size: 'xs',
          class: 'pe-7'
        },
        {
          increment: true,
          size: 'sm',
          class: 'pe-8'
        },
        {
          increment: true,
          size: 'md',
          class: 'pe-9'
        },
        {
          increment: true,
          size: 'lg',
          class: 'pe-10'
        },
        {
          increment: true,
          size: 'xl',
          class: 'pe-11'
        }
      ],
      defaultVariants: {
        size: 'md',
        color: 'primary',
        variant: 'outline'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        inputNumber: {
          slots: {
            root: 'relative inline-flex items-center',
            base: [
              'w-full rounded-md border-0 placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75',
              'transition-colors'
            ],
            increment: 'absolute flex items-center',
            decrement: 'absolute flex items-center'
          },
          variants: {
            fieldGroup: {
              horizontal: {
                root: 'group has-focus-visible:z-[1]',
                base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
              },
              vertical: {
                root: 'group has-focus-visible:z-[1]',
                base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
              }
            },
            color: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            size: {
              xs: 'px-2 py-1 text-xs gap-1',
              sm: 'px-2.5 py-1.5 text-xs gap-1.5',
              md: 'px-2.5 py-1.5 text-sm gap-1.5',
              lg: 'px-3 py-2 text-sm gap-2',
              xl: 'px-3 py-2 text-base gap-2'
            },
            variant: {
              outline: 'text-highlighted bg-default ring ring-inset ring-accented',
              soft: 'text-highlighted bg-elevated/50 hover:bg-elevated focus:bg-elevated disabled:bg-elevated/50',
              subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
              ghost: 'text-highlighted bg-transparent hover:bg-elevated focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
              none: 'text-highlighted bg-transparent'
            },
            disabled: {
              true: {
                increment: 'opacity-75 cursor-not-allowed',
                decrement: 'opacity-75 cursor-not-allowed'
              }
            },
            orientation: {
              horizontal: {
                base: 'text-center',
                increment: 'inset-y-0 end-0 pe-1',
                decrement: 'inset-y-0 start-0 ps-1'
              },
              vertical: {
                increment: 'top-0 end-0 pe-1 [&>button]:py-0 scale-80',
                decrement: 'bottom-0 end-0 pe-1 [&>button]:py-0 scale-80'
              }
            },
            highlight: {
              true: ''
            },
            increment: {
              false: ''
            },
            decrement: {
              false: ''
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary'
            },
            {
              color: 'primary',
              highlight: true,
              class: 'ring ring-inset ring-primary'
            },
            {
              color: 'neutral',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-inverted'
            },
            {
              color: 'neutral',
              highlight: true,
              class: 'ring ring-inset ring-inverted'
            },
            {
              orientation: 'horizontal',
              decrement: false,
              class: 'text-start'
            },
            {
              decrement: true,
              size: 'xs',
              class: 'ps-7'
            },
            {
              decrement: true,
              size: 'sm',
              class: 'ps-8'
            },
            {
              decrement: true,
              size: 'md',
              class: 'ps-9'
            },
            {
              decrement: true,
              size: 'lg',
              class: 'ps-10'
            },
            {
              decrement: true,
              size: 'xl',
              class: 'ps-11'
            },
            {
              increment: true,
              size: 'xs',
              class: 'pe-7'
            },
            {
              increment: true,
              size: 'sm',
              class: 'pe-8'
            },
            {
              increment: true,
              size: 'md',
              class: 'pe-9'
            },
            {
              increment: true,
              size: 'lg',
              class: 'pe-10'
            },
            {
              increment: true,
              size: 'xl',
              class: 'pe-11'
            }
          ],
          defaultVariants: {
            size: 'md',
            color: 'primary',
            variant: 'outline'
          }
        }
      }
    })
  ]
})
为便于阅读,compoundVariants 中的某些颜色已省略。请在 GitHub 上查看源代码。

更新日志

18589— feat: 处理 increment / decrement 作为布尔值 (#4805)

11a03— fix: labelKeyvalueKey 的点表示法类型支持 (#4933)

83b03— feat!: 重命名 nullify 修饰符为 nullable 并添加 optional (#4838)

61b60— 功能:允许传递组件而不是名称 (#4766)

a0963— feat!: 重命名 ButtonGroup (#4596)

5cb65— 特性:导入 @nuxt/ui-pro 组件

7133f— 修复:update:model-value 事件类型错误 (#4853)

ee484— chore: 更新依赖 reka-ui 到 v2.4.1 (v3) (#4586)

6f2ce— 重构:统一 emits 声明的语法 (#4512)

f7613— chore:更新依赖 reka-ui 到 ^2.3.0 (v3)(#4234)

2e4c3— fix: 处理按钮组内部

c7fba— feat: 添加 increment-disabled / decrement-disabled prop (#4141)

e6e51— fix:class 应该优先于 ui 属性

39c86— fix:@nuxt/module-builder 升级后重构类型(#3855)

4d817— chore: 清理函数顺序

f5e62— feat: 添加对 stepSnappingdisableWheelChange prop 的支持 (#3731)