Skip to content

数字输入 Input Number

专门输入数字的输入框。它和 Input 非常类似,拥有 Input 大部分功能。

基础使用

这个组件用于数字输入。传入 modelValue 进入受控模式。不传或者为 undefined 则为非受控模式,此时可以传入 defaultValue 属性作为默认值。

<template>
	<px-space>
		<px-input-number placeholder="Please input number" v-model="input"></px-input-number>
		<px-input-number placeholder="Please input number" :default-value="0"></px-input-number>
	</px-space>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const input = ref(47)
</script>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

值域

通过 maxmin 属性设置取值范围,左右都是闭区间。

<template>
	<px-input-number
		placeholder="Please input number"
		v-model="input"
		:min="-114"
		:max="514"
	></px-input-number>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const input = ref()
</script>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

步长

通过 step 属性设置加减按钮的步长。strickStep 属性为 true 时,限制值必须为 step 的整数倍。

<template>
	<px-space direction="vertical">
		<px-input-number
			placeholder="Please input number"
			v-model="input1"
			:step="2"
			:min="-13"
			:max="23"
		></px-input-number>
		<px-input-number
			placeholder="Please input number"
			v-model="input2"
			:step="2"
			strick-step
			:min="-13"
			:max="23"
		></px-input-number>
	</px-space>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const input1 = ref(0)
const input2 = ref(0)
</script>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

精度

通过 precision 属性设置精度,该属性会设置值精确到的小数位。

<template>
	<px-input-number
		placeholder="Please input number"
		v-model="input"
		:precision="4"
	></px-input-number>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const input = ref(1919.81)
</script>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

自定义模板

通过同时传入 formatallowInputparse 三个属性设置数字展示模板,例如实现展示附带单位,千分位数。

<template>
	<px-space direction="vertical">
		<px-input-number
			direction="vertical"
			placeholder="Please input number"
			v-model="inputUnit"
			:precision="precision"
			:format="formatUnit"
			:allow-input="allowInputUnit"
			:parse="parseUnit"
		></px-input-number>
		<px-input-number
			placeholder="Please input number"
			v-model="inputSeparator"
			:format="formatSeparator"
			:allow-input="allowInputSeparator"
			:parse="parseSeparator"
		></px-input-number>
	</px-space>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const inputUnit = ref(100)
const precision = ref(4)

const formatUnit = (value: number | null | undefined) => {
	if (value === undefined || value === null || isNaN(value)) {
		return ''
	}
	return value.toFixed(precision.value) + '%'
}
const reg4NumberUnit = /^[+-]?\d+(?:\.\d*)?(%)?$/
const allowInputUnit = (value: string) => {
	if (!value.length) {
		return true
	}
	return reg4NumberUnit.test(value)
}
const parseUnit = (value: string) => {
	if (!value.length) {
		return 0
	}
	return parseFloat(value)
}

function thousandSeparator(num: number): string {
	const numStr = Math.abs(num).toString()
	const [int, decimal] = numStr.split('.')

	const formattedInt = int.replace(/\B(?=(\d{3})+(?!\d))/g, ',')

	let result
	if (decimal) {
		const formattedDecimal = decimal.replace(/(\d{3})(?=\d)/g, '$1,')
		result = `${formattedInt}.${formattedDecimal}`
	} else {
		result = formattedInt
	}

	return num < 0 ? '-' + result : result
}
const inputSeparator = ref(12345.6789)

const formatSeparator = (value: number | null | undefined) => {
	if (value === undefined || value === null || isNaN(value)) {
		return ''
	}
	return thousandSeparator(value)
}
const reg4Number = /^[+-]?\d+(?:\.\d*)?$/
const allowInputSeparator = (value: string) => {
	if (!value.length) {
		return true
	}
	return reg4Number.test(value.split(',').join(''))
}
const parseSeparator = (value: string) => {
	if (!value.length) {
		return 0
	}
	return parseFloat(value.split(',').join(''))
}
</script>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

按钮位置

加减按钮的位置也是可以配置的,通过 buttonPlacement 属性设置。

<template>
	<px-space>
		<px-input-number
			placeholder="Please input number"
			button-placement="start"
		></px-input-number>
		<px-input-number
			placeholder="Please input number"
			button-placement="start-reverse"
		></px-input-number>
		<px-input-number placeholder="Please input number"></px-input-number>
		<px-input-number
			placeholder="Please input number"
			button-placement="end-reverse"
		></px-input-number>
		<px-input-number
			placeholder="Please input number"
			button-placement="both"
		></px-input-number>
		<px-input-number
			placeholder="Please input number"
			button-placement="both-reverse"
		></px-input-number>
	</px-space>
</template>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

更多配置

InputNumber 还拥有 Input 组件的大部分功能。

Disabled, Readonly, Loading & Clearable

Shape

Size

Slot

+
s

Composite

Status

Expose

<template>
	<px-space direction="vertical">
		<h4>Disabled, Readonly, Loading & Clearable</h4>
		<px-space>
			<px-input-number
				placeholder="Please input number"
				disabled
				:default-value="0"
			></px-input-number>
			<px-input-number
				placeholder="Please input number"
				readonly
				:default-value="0"
			></px-input-number>
			<px-input-number
				placeholder="Please input number"
				loading
				:default-value="0"
			></px-input-number>
			<px-input-number
				placeholder="Please input number"
				clearable
				:default-value="0"
			></px-input-number>
		</px-space>
		<h4>Shape</h4>
		<px-space>
			<px-input-number
				placeholder="Please input number"
				shape="round"
				:default-value="0"
			></px-input-number>
			<px-input-number placeholder="Please input number" :default-value="0"></px-input-number>
		</px-space>
		<h4>Size</h4>
		<px-space>
			<px-input-number
				placeholder="Please input number"
				size="small"
				:default-value="0"
			></px-input-number>
			<px-input-number placeholder="Please input number" :default-value="0"></px-input-number>
			<px-input-number
				placeholder="Please input number"
				size="large"
				:default-value="0"
			></px-input-number>
		</px-space>
		<h4>Slot</h4>
		<px-space>
			<px-input-number placeholder="Please input number" :default-value="1">
				<template #prefix>+</template>
				<template #suffix>s</template>
			</px-input-number>
			<px-input-number placeholder="Please input number" :default-value="0">
				<template #prepend>
					<IconBolt></IconBolt>
				</template>
			</px-input-number>
			<px-input-number placeholder="Please input number">
				<template #append>
					<IconBolt></IconBolt>
				</template>
			</px-input-number>
		</px-space>
		<h4>Composite</h4>
		<px-space>
			<px-input-group>
				<px-input-group-label>
					<IconBolt></IconBolt>
				</px-input-group-label>
				<px-input-number placeholder="Please input number" :default-value="0">
				</px-input-number>
				<px-button>Confirm</px-button>
			</px-input-group>
		</px-space>
		<h4>Status</h4>
		<px-space>
			<px-input-number placeholder="Please input number"> </px-input-number>
			<px-input-number placeholder="Please input number" status="success"> </px-input-number>
			<px-input-number placeholder="Please input number" status="warning"> </px-input-number>
			<px-input-number placeholder="Please input number" status="error"> </px-input-number>
		</px-space>
		<h4>Expose</h4>
		<px-space direction="vertical">
			<px-space>
				<px-button theme="info" @click="focusHandler">Focus</px-button>
				<px-button theme="info" @click="blurHandler">Blur</px-button>
				<px-button theme="info" @click="selectHandler">Select</px-button>
				<px-button theme="warning" @click="clearHandler">Clear</px-button>
			</px-space>
			<px-input-number placeholder="Please input" ref="inputNumberRef"></px-input-number>
		</px-space>
	</px-space>
</template>

<script setup lang="ts">
import { IconBolt } from '@pixelium/web-vue/icon-hn/es'
import { ref } from 'vue'
import { InputNumber } from '@pixelium/web-vue'

// If on-demand import
// import { InputNumber } from '@pixelium/web-vue/es'

const inputNumberRef = ref<InstanceType<typeof InputNumber>>(null)

const focusHandler = () => {
	inputNumberRef.value?.focus()
}
const blurHandler = () => {
	inputNumberRef.value?.blur()
}
const clearHandler = () => {
	inputNumberRef.value?.clear()
}
const selectHandler = () => {
	inputNumberRef.value?.select()
}
</script>

<style lang="css" scoped>
.px-input-number {
	width: 320px;
}
</style>

API

InputNumberProps

属性类型可选默认值描述版本
modelValuestring | null数字输入框的值(受控模式),支持 v-model0.0.2
defaultValuestring | null数字输入框的默认值(非受控模式)。0.0.2
placeholderstring占位符文本。0.0.2
disabledbooleanfalse是否禁用。0.0.2
readonlybooleanfalse是否只读。0.0.2
maxnumberNumber.MAX_SAFE_INTEGER最大值(闭区间)。0.0.2
minnumberNumber.MIN_SAFE_INTEGER最小值(闭区间)。0.0.2
stepnumber1加减按钮的步长。0.0.2
precisionnumber精确到小数位,取值为 [0, 100] 的整数。0.0.2
strickStepbooleanfalse严格步长,限制值必须为 step 的整数倍。0.0.2
format(value: number | Nullish) => string将数字值转换为字符串展示的函数。0.0.2
allowInput(value: string) => boolean检查数字输入框的文本是否允许输入的函数。0.0.2
parse(value: string) => number将数字输入框的文本转换为数字值的函数。0.0.2
clearablebooleanfalse是否显示清除按钮。0.0.2
loadingbooleanfalse是否显示加载状态。0.0.2
size'medium' | 'large' | 'small''medium'数字输入框尺寸。0.0.2
shape'default' | 'round''default'数字输入框形状。0.0.2
borderRadiusNumberOrPercentage | NumberOrPercentage[]圆角半径,优先级高于 shape,与 CSS border-radius 行为一致;单值或长度为 1 的数组 → 四角同时生效;长度为 2 的数组 → [左上 & 右下, 右上 & 左下];长度为 3 的数组 → [左上, 右上 & 左下, 右下];长度为 4 的数组 → 按顺时针顺序依次作用于四角。0.0.2
buttonPlacementboolean'end'加减按钮的位置。0.0.2
status'success' | 'warning' | 'error' | 'normal''normal'表单验证状态。0.0.2
autofocusbooleanfalse原生 <input>autofocus 属性。0.0.2

InputNumberEvents

事件参数描述版本
inputvalue: number, e: Event数字输入框输入时的回调。0.0.2
update:modelValuevalue: number更新 modelValue 的回调。0.0.2
changevalue: number, e: Event | undefined输入内容变化时的回调。0.0.2
clearvalue: number点击清除文本按钮,清除内容时的回调。0.0.2
blure: FocusEvent数字输入框失焦时的回调。0.0.2
focuse: FocusEvent数字输入框聚焦时的回调。0.0.2

InputNumberSlots

插槽参数描述版本
prefix前缀内容。0.0.2
suffix后缀内容。0.0.2

InputNumberExpose

属性类型可选默认值描述版本
focus() => void聚焦到当前数字输入框。0.0.2
blur() => void取消聚焦当前数字输入框。0.0.2
clear() => void清空当前数字输入框。0.0.2
select() => void选中当前数字输入框内容。0.0.2

NumberOrPercentage

ts
export type NumberOrPercentage = number | `${number}%`