Skip to content

Commit c1e6811

Browse files
author
Tenny
committed
fix(Input): 增加只允许输入数字
1 parent 20f328f commit c1e6811

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

docs/components/input.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010

1111
const inputInt = ref('')
1212

13+
const input1 = ref('')
14+
const input2 = ref('')
15+
const input3 = ref('')
16+
1317
function numericParse(value: string) {
1418
let val = parseInt(value, 10)
1519
if (Number.isNaN(val)) {
@@ -64,6 +68,27 @@
6468
</CodePreview>
6569
</ClientOnly>
6670

71+
### 允许输入的值
72+
73+
通过传递 `allow-input` 来限制输入的值。`integer` 只能输入正整数, `number` 只能输入正数;以 `-` 开头表明允许输入负数; 以 `.2` 结尾表明小数点后精度; 例如: `-number.4` 表明允许输入数字,且小数点后保留4位小数。
74+
75+
<ClientOnly>
76+
<CodePreview>
77+
<textarea lang="vue" v-pre>
78+
<script setup lang="ts">
79+
</script>
80+
<template>
81+
<hr />
82+
</template>
83+
</textarea>
84+
<template #preview>
85+
<Input v-model="input1" placeholder="只能输入正整数" allow-input="integer" />
86+
<Input v-model="input2" placeholder="只能输入整数" allow-input="-integer" />
87+
<Input v-model="input3" placeholder="输入数字,保留2位小数" allow-input="-number.2" />
88+
</template>
89+
</CodePreview>
90+
</ClientOnly>
91+
6792
### 禁用状态
6893

6994
通过 `disabled` 属性设置输入框为禁用状态。
@@ -87,6 +112,7 @@
87112
| `model-value` / `v-model` | 绑定值 | `string` ||
88113
| `placeholder` | 占位文本 | `string` ||
89114
| `parser` | 输入时解析值 | `(value: string) => string` ||
115+
| `allow-input` | 允许输入的值; `number``integer`,前面包含 `-` 表明允许小数, 以 `.2` 结尾表明小数点后精度 | `string` | - |
90116

91117
### Input Exposes
92118

src/components/input/Input.vue

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ const props = withDefaults(
2727
parser?: (value: string) => string;
2828
modelValue?: string | number;
2929
disabled?: boolean;
30+
/** number, integer */
31+
allowInput?: string;
3032
}>(),
3133
{
3234
htmlType: 'text',
3335
placeholder: '',
3436
autosize: false,
3537
disabled: undefined,
38+
allowInput: undefined,
3639
},
3740
);
3841
@@ -46,10 +49,49 @@ function focus() {
4649
}
4750
}
4851
52+
function numberInputParse(
53+
value: string,
54+
config: { integer: boolean; negative: boolean; precition: number },
55+
) {
56+
let val = value;
57+
let negative = config.negative ? '-?' : '';
58+
if (config.integer) {
59+
const match = val.match(new RegExp(`^(${negative}\\d*)`));
60+
if (match != null) {
61+
return match[1];
62+
}
63+
return val.substring(0, val.length - 1);
64+
}
65+
const match = val.match(
66+
new RegExp(
67+
`^(${negative}\\d+\\.\\d{0,${config.precition}})|(${negative}\\d*)`,
68+
),
69+
);
70+
if (match != null) {
71+
val = match[1] || match[2];
72+
} else {
73+
val = '';
74+
}
75+
return match != null ? match[1] || match[2] : '';
76+
}
77+
4978
function handleInput(e: Event) {
5079
const $target = e.target as HTMLInputElement;
5180
let value = $target.value;
5281
emits('input', e);
82+
if (props.allowInput != null) {
83+
let dotIndex = props.allowInput.indexOf('.');
84+
let precition =
85+
dotIndex === -1
86+
? dotIndex
87+
: parseInt(props.allowInput.substring(dotIndex + 1));
88+
value = numberInputParse(value, {
89+
integer: props.allowInput.includes('integer'),
90+
negative: props.allowInput.startsWith('-'),
91+
precition: precition,
92+
});
93+
$target.value = String(value);
94+
}
5395
if (props.parser != null) {
5496
value = props.parser(value) as string;
5597
$target.value = String(value);

src/hooks/useFormDisabled.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export default function useDisabled(
1717
return toValue<boolean>(formItemDisabeld as boolean);
1818
if (toValue(formDisabled) != null)
1919
return toValue<boolean>(formDisabled as boolean);
20+
return false;
2021
});
2122

2223
return isDisabled;

src/utils/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export function impactDetect(
126126
const maxWidth = window.innerWidth + scrollLeft - 10;
127127
// 判断 垂直 方向是否在显示区域内
128128
let y = targetRect.top + scrollTop - topDiff;
129-
let yEnd = y + popoverRect.height;
129+
const yEnd = y + popoverRect.height;
130130
// 1. 首先判断下边界是否超出屏幕
131131
if (yEnd > maxHeight) {
132132
// 下边距超出屏幕
@@ -154,7 +154,7 @@ export function impactDetect(
154154
// 判断 水平 方向是否在显示区域内
155155
// 1. 首先判断右边界是否超出屏幕
156156
let x = targetRect.left + scrollLeft - leftDiff;
157-
let xEnd = x + popoverRect.width;
157+
const xEnd = x + popoverRect.width;
158158
if (xEnd > maxWidth) {
159159
// 右边距超出屏幕
160160
if (mainAlign === 'top' || mainAlign === 'bottom') {

0 commit comments

Comments
 (0)