diff --git a/src/form/__test__/__snapshots__/demo.test.jsx.snap b/src/form/__test__/__snapshots__/demo.test.jsx.snap
index c8c80c411..ad6429510 100644
--- a/src/form/__test__/__snapshots__/demo.test.jsx.snap
+++ b/src/form/__test__/__snapshots__/demo.test.jsx.snap
@@ -1385,13 +1385,13 @@ exports[`Form > Form horizontalVue demo works fine 1`] = `
>
+
0/50
@@ -3157,13 +3157,13 @@ exports[`Form > Form mobileVue demo works fine 1`] = `
>
+
0/50
@@ -4780,13 +4780,13 @@ exports[`Form > Form verticalVue demo works fine 1`] = `
>
+
0/50
diff --git a/src/hooks/useLengthLimit.tsx b/src/hooks/useLengthLimit.tsx
new file mode 100644
index 000000000..4f93a96df
--- /dev/null
+++ b/src/hooks/useLengthLimit.tsx
@@ -0,0 +1,51 @@
+import { computed, ComputedRef } from 'vue';
+import isNumber from 'lodash/isNumber';
+import isObject from 'lodash/isObject';
+import log from '../_common/js/log';
+import { getCharacterLength, getUnicodeLength, limitUnicodeMaxLength } from '../_common/js/utils/helper';
+
+export interface UseLengthLimitParams {
+ value: string;
+ maxlength: number;
+ maxcharacter: number;
+ allowInputOverMax: boolean;
+}
+
+export default function useLengthLimit(params: ComputedRef) {
+ // 文本超出数量限制时,是否允许继续输入
+ const getValueByLimitNumber = (inputValue: string) => {
+ const { allowInputOverMax, maxlength, maxcharacter } = params.value;
+ if (!(maxlength || maxcharacter) || allowInputOverMax || !inputValue) return inputValue;
+ if (maxlength) {
+ // input value could be unicode 😊
+ return limitUnicodeMaxLength(inputValue, maxlength);
+ }
+ if (maxcharacter) {
+ const r = getCharacterLength(inputValue, maxcharacter);
+ if (isObject(r)) {
+ return r.characters;
+ }
+ }
+ };
+
+ const limitNumber = computed(() => {
+ const { maxlength, maxcharacter, value } = params.value;
+ if (isNumber(value)) return String(value);
+ if (maxlength && maxcharacter) {
+ log.warn('Input', 'Pick one of maxlength and maxcharacter please.');
+ }
+ if (maxlength) {
+ const length = value?.length ? getUnicodeLength(value) : 0;
+ return `${length}/${maxlength}`;
+ }
+ if (maxcharacter) {
+ return `${getCharacterLength(value || '')}/${maxcharacter}`;
+ }
+ return '';
+ });
+
+ return {
+ limitNumber,
+ getValueByLimitNumber,
+ };
+}
diff --git a/src/input/input.tsx b/src/input/input.tsx
index 6f350b6e8..6f8081f32 100644
--- a/src/input/input.tsx
+++ b/src/input/input.tsx
@@ -5,16 +5,15 @@ import {
CloseCircleFilledIcon as TCloseCircleFilledIcon,
} from 'tdesign-icons-vue-next';
import isFunction from 'lodash/isFunction';
-import isObject from 'lodash/isObject';
import config from '../config';
import InputProps from './props';
import { InputValue, TdInputProps } from './type';
import { useDefault, extendAPI } from '../shared';
-import { getCharacterLength, limitUnicodeMaxLength } from '../_common/js/utils/helper';
import { FormItemInjectionKey } from '../form/const';
import { useFormDisabled } from '../form/hooks';
import { usePrefixClass } from '../hooks/useClass';
import { useTNodeJSX } from '../hooks/tnode';
+import useLengthLimit from '../hooks/useLengthLimit';
const { prefix } = config;
@@ -76,6 +75,15 @@ export default defineComponent({
return false;
});
+ const limitParams = computed(() => ({
+ value: [undefined, null].includes(innerValue.value) ? undefined : String(innerValue.value),
+ maxlength: Number(props.maxlength),
+ maxcharacter: props.maxcharacter,
+ allowInputOverMax: props.allowInputOverMax,
+ }));
+
+ const { getValueByLimitNumber } = useLengthLimit(limitParams);
+
const setInputValue = (v: InputValue = '') => {
const input = inputRef.value as HTMLInputElement;
const sV = String(v);
@@ -96,22 +104,6 @@ export default defineComponent({
inputValueChangeHandle(e);
};
- // 文本超出数量限制时,是否允许继续输入
- const getValueByLimitNumber = (inputValue: string) => {
- const { allowInputOverMax, maxlength, maxcharacter } = props;
- if (!(maxlength || maxcharacter) || allowInputOverMax || !inputValue) return inputValue;
- if (maxlength) {
- // input value could be unicode 😊
- return limitUnicodeMaxLength(inputValue, Number(maxlength));
- }
- if (maxcharacter) {
- const r = getCharacterLength(inputValue, maxcharacter);
- if (isObject(r)) {
- return r.characters;
- }
- }
- };
-
const inputValueChangeHandle = (e: Event) => {
const { value } = e.target as HTMLInputElement;
innerValue.value = getValueByLimitNumber(value);
@@ -248,6 +240,7 @@ export default defineComponent({
// 不传给 input 原生元素 maxlength,浏览器默认行为会按照 unicode 进行限制,与 maxLength API 违背
const inputAttrs = {
ref: inputRef,
+ class: inputClasses.value,
value: innerValue.value,
name: props.name,
type: renderType.value,
@@ -271,7 +264,7 @@ export default defineComponent({
{renderPrefix()}
@@ -133,13 +133,13 @@ exports[`Textarea > Textarea customVue demo works fine 1`] = `
>
+
0/100
@@ -214,6 +214,7 @@ exports[`Textarea > Textarea maxcharacterVue demo works fine 1`] = `
+
0/500
@@ -234,13 +235,13 @@ exports[`Textarea > Textarea maxlengthVue demo works fine 1`] = `
>
+
0/500
@@ -406,13 +407,13 @@ exports[`Textarea > Textarea mobileVue demo works fine 1`] = `
>
+
0/500
@@ -447,6 +448,7 @@ exports[`Textarea > Textarea mobileVue demo works fine 1`] = `
+
0/500
@@ -539,13 +541,13 @@ exports[`Textarea > Textarea mobileVue demo works fine 1`] = `
>
+
0/500
@@ -575,13 +577,13 @@ exports[`Textarea > Textarea mobileVue demo works fine 1`] = `
>
+
0/500
@@ -632,13 +634,13 @@ exports[`Textarea > Textarea mobileVue demo works fine 1`] = `
>
+
0/100
diff --git a/src/textarea/textarea.tsx b/src/textarea/textarea.tsx
index 53188ffcf..3c4abc4a1 100644
--- a/src/textarea/textarea.tsx
+++ b/src/textarea/textarea.tsx
@@ -1,5 +1,6 @@
import { computed, ref, onMounted, defineComponent, toRefs, nextTick, watch, inject } from 'vue';
-import { getCharacterLength, useVModel } from '../shared';
+import { useVModel } from '../shared';
+import useLengthLimit from '../hooks/useLengthLimit';
import config from '../config';
import props from './props';
import { TextareaValue } from './type';
@@ -41,6 +42,15 @@ export default defineComponent({
const { value, modelValue } = toRefs(props);
const [innerValue, setInnerValue] = useVModel(value, modelValue, props.defaultValue, props.onChange);
+ const limitParams = computed(() => ({
+ value: [undefined, null].includes(innerValue.value) ? undefined : String(innerValue.value),
+ maxlength: Number(props.maxlength),
+ maxcharacter: props.maxcharacter,
+ allowInputOverMax: props.allowInputOverMax,
+ }));
+
+ const { limitNumber, getValueByLimitNumber } = useLengthLimit(limitParams);
+
const setInputValue = (v: TextareaValue = '') => {
const input = textareaRef.value;
const sV = String(v);
@@ -75,32 +85,12 @@ export default defineComponent({
const textareaValueChangeHandle = () => {
const textarea = textareaRef.value;
- if (
- !props.allowInputOverMax &&
- props.maxcharacter &&
- props.maxcharacter > 0 &&
- !Number.isNaN(props.maxcharacter)
- ) {
- const { characters = '' } = getCharacterLength(textarea.value, props.maxcharacter) as {
- length: number;
- characters: string;
- };
- setInnerValue(characters);
- } else {
- setInnerValue(textarea.value);
- }
+ setInnerValue(getValueByLimitNumber(textarea.value));
+
nextTick(() => setInputValue(innerValue.value));
adjustTextareaHeight();
};
- const textareaLength = computed(() => {
- const _value = innerValue.value ? String(innerValue.value) : '';
- if (props.maxcharacter) {
- return getCharacterLength(_value);
- }
- return _value.length;
- });
-
const handleCompositionend = (e: InputEvent | CompositionEvent) => {
textareaValueChangeHandle();
};
@@ -143,32 +133,30 @@ export default defineComponent({
if (!isShowIndicator) {
return null;
}
- return (
-
- {`${textareaLength.value}/${props.maxcharacter || props.maxlength}`}
-
- );
+ return {limitNumber.value}
;
+ };
+
+ const textareaAttrs = {
+ ref: textareaRef,
+ class: textareaInnerClasses.value,
+ style: textareaStyle.value,
+ value: innerValue.value,
+ name: props.name,
+ // maxlength: props.maxlength,
+ disabled: isDisabled.value,
+ placeholder: props.placeholder,
+ readonly: props.readonly,
+ onFocus: handleFocus,
+ onBlur: handleBlur,
+ onInput: handleInput,
+ onCompositionend: handleCompositionend,
};
return (
{renaderLabel()}
-
+
{readerIndicator()}