Textarea 多行输入
多行输入 —— 与 Input 同色系,支持自动撑高、字符计数、resize 控制。
基础用法
视觉与 Input 共用一套色系。rows 控制初始行数,用户可以拖右下角调整高度。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const note = ref('');
</script>
<template>
<CfTextarea v-model="note" placeholder="说点什么…" :rows="3" />
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const note = ref('');
</script>
<template>
<CfTextarea v-model="note" placeholder="说点什么…" :rows="3" />
</template> import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [note, setNote] = useState('');
return (
<>
<CfTextarea value={note} onChange={setNote} placeholder="说点什么…" rows={3} />
</>
);
} import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [note, setNote] = useState('');
return (
<>
<CfTextarea value={note} onChange={setNote} placeholder="说点什么…" rows={3} />
</>
);
} 视觉变体
outline 是默认描边,filled 提供浅色填充背景(密集表单常用),ghost 完全透明只在交互态显示边界。
与 Input 的同名变体一一对应,可以在同一个表单里混用而不破坏视觉一致性。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const a = ref<string>('');
const b = ref<string>('');
const c = ref<string>('');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="a" variant="outline" placeholder="outline —— 默认描边" :rows="2" />
<CfTextarea v-model="b" variant="filled" placeholder="filled —— 浅色填充背景" :rows="2" />
<CfTextarea v-model="c" variant="ghost" placeholder="ghost —— 透明,只在 hover/focus 时可见" :rows="2" />
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const a = ref<string>('');
const b = ref<string>('');
const c = ref<string>('');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="a" variant="outline" placeholder="outline —— 默认描边" :rows="2" />
<CfTextarea v-model="b" variant="filled" placeholder="filled —— 浅色填充背景" :rows="2" />
<CfTextarea v-model="c" variant="ghost" placeholder="ghost —— 透明,只在 hover/focus 时可见" :rows="2" />
</div>
</template> import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
return (
<>
<CfTextarea variant="outline" placeholder="outline" rows={2} />
<CfTextarea variant="filled" placeholder="filled" rows={2} />
<CfTextarea variant="ghost" placeholder="ghost" rows={2} />
</>
);
} import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
return (
<>
<CfTextarea variant="outline" placeholder="outline" rows={2} />
<CfTextarea variant="filled" placeholder="filled" rows={2} />
<CfTextarea variant="ghost" placeholder="ghost" rows={2} />
</>
);
} 尺寸
3 档尺寸控制字号与内边距,与 Input 的 size 一致。表单中通常与同行 Input 保持一致。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const sm = ref<string>('');
const md = ref<string>('');
const lg = ref<string>('');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="sm" size="sm" placeholder="size = sm(紧凑)" :rows="2" />
<CfTextarea v-model="md" size="md" placeholder="size = md(默认)" :rows="2" />
<CfTextarea v-model="lg" size="lg" placeholder="size = lg(宽松)" :rows="2" />
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const sm = ref<string>('');
const md = ref<string>('');
const lg = ref<string>('');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="sm" size="sm" placeholder="size = sm(紧凑)" :rows="2" />
<CfTextarea v-model="md" size="md" placeholder="size = md(默认)" :rows="2" />
<CfTextarea v-model="lg" size="lg" placeholder="size = lg(宽松)" :rows="2" />
</div>
</template> import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const sm = '';
const md = '';
const lg = '';
return (
<>
<CfTextarea size="sm" placeholder="size = sm" rows={2} />
<CfTextarea size="md" placeholder="size = md" rows={2} />
<CfTextarea size="lg" placeholder="size = lg" rows={2} />
</>
);
} import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const sm = '';
const md = '';
const lg = '';
return (
<>
<CfTextarea size="sm" placeholder="size = sm" rows={2} />
<CfTextarea size="md" placeholder="size = md" rows={2} />
<CfTextarea size="lg" placeholder="size = lg" rows={2} />
</>
);
} 状态
disabled 完全禁用、readonly 只读(可选中复制不能修改)、error 让边框与焦点环变红用于校验失败提示。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const a = ref<string>('禁用状态下不可输入也不可获取焦点');
const b = ref<string>('只读:可以选中复制,但不能修改');
const c = ref<string>('错误态:边框与焦点环都会变红,常用于校验失败');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="a" disabled :rows="2" />
<CfTextarea v-model="b" readonly :rows="2" />
<CfTextarea v-model="c" error :rows="2" />
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const a = ref<string>('禁用状态下不可输入也不可获取焦点');
const b = ref<string>('只读:可以选中复制,但不能修改');
const c = ref<string>('错误态:边框与焦点环都会变红,常用于校验失败');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="a" disabled :rows="2" />
<CfTextarea v-model="b" readonly :rows="2" />
<CfTextarea v-model="c" error :rows="2" />
</div>
</template> import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [a, setA] = useState<string>('禁用状态下不可输入也不可获取焦点');
const [b, setB] = useState<string>('只读:可以选中复制,但不能修改');
const [c, setC] = useState<string>('错误态:边框与焦点环都会变红,常用于校验失败');
return (
<>
<div className="demo-stack">
<CfTextarea value={a} onChange={setA} disabled rows={2} />
<CfTextarea value={b} onChange={setB} readonly rows={2} />
<CfTextarea value={c} onChange={setC} error rows={2} />
</div>
</>
);
} import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [a, setA] = useState<string>('禁用状态下不可输入也不可获取焦点');
const [b, setB] = useState<string>('只读:可以选中复制,但不能修改');
const [c, setC] = useState<string>('错误态:边框与焦点环都会变红,常用于校验失败');
return (
<>
<div className="demo-stack">
<CfTextarea value={a} onChange={setA} disabled rows={2} />
<CfTextarea value={b} onChange={setB} readonly rows={2} />
<CfTextarea value={c} onChange={setC} error rows={2} />
</div>
</>
);
} 字符计数
maxlength 设上限(原生限制),show-count 在右下角显示当前字符数。超过上限会变红(虽然 maxlength 会先拦截)。
背景 视口
0 / 50
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const bio = ref('');
</script>
<template>
<CfTextarea
v-model="bio"
placeholder="个人简介(最多 50 字)"
:rows="3"
:maxlength="50"
show-count
/>
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const bio = ref('');
</script>
<template>
<CfTextarea
v-model="bio"
placeholder="个人简介(最多 50 字)"
:rows="3"
:maxlength="50"
show-count
/>
</template> import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [bio, setBio] = useState('');
return (
<>
<CfTextarea value={bio} onChange={setBio} placeholder="个人简介(最多 50 字)" rows={3} maxlength={50} showCount />
</>
);
} import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [bio, setBio] = useState('');
return (
<>
<CfTextarea value={bio} onChange={setBio} placeholder="个人简介(最多 50 字)" rows={3} maxlength={50} showCount />
</>
);
} 自动撑高
auto-resize 让框跟随内容增长,自动隐藏 resize 把手。适合不确定行数的场景(如评论、备注)。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const draft = ref('试着多敲几行回车,框会自动撑高,没有滚动条。\n这是第二行。');
</script>
<template>
<CfTextarea
v-model="draft"
variant="filled"
auto-resize
placeholder="自动撑高的多行输入"
/>
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const draft = ref('试着多敲几行回车,框会自动撑高,没有滚动条。\n这是第二行。');
</script>
<template>
<CfTextarea
v-model="draft"
variant="filled"
auto-resize
placeholder="自动撑高的多行输入"
/>
</template> import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [draft, setDraft] = useState('试着多敲几行回车,框会自动撑高,没有滚动条。\n这是第二行。');
return (
<>
<CfTextarea value={draft} onChange={setDraft} variant="filled" autoResize placeholder="自动撑高的多行输入" />
</>
);
} import { useState } from 'react';
import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
const [draft, setDraft] = useState('试着多敲几行回车,框会自动撑高,没有滚动条。\n这是第二行。');
return (
<>
<CfTextarea value={draft} onChange={setDraft} variant="filled" autoResize placeholder="自动撑高的多行输入" />
</>
);
} Resize 控制
resize 决定用户拖拽时允许的方向。none 完全锁定,vertical 是默认行为,horizontal 仅横向,both 横纵都可拖。
当 auto-resize 开启时本属性会被覆盖为 none。
背景 视口
<script setup lang="ts">
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const a = ref<string>('');
const b = ref<string>('');
const c = ref<string>('');
const d = ref<string>('');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="a" resize="none" placeholder="resize = none —— 完全锁定,无拖拽把手" :rows="2" />
<CfTextarea v-model="b" resize="vertical" placeholder="resize = vertical —— 仅纵向可拖(默认)" :rows="2" />
<CfTextarea v-model="c" resize="horizontal" placeholder="resize = horizontal —— 仅横向可拖" :rows="2" />
<CfTextarea v-model="d" resize="both" placeholder="resize = both —— 横纵都可拖" :rows="2" />
</div>
</template> <script setup>
import { ref } from 'vue';
import { CfTextarea } from '@chufix-design/vue';
const a = ref<string>('');
const b = ref<string>('');
const c = ref<string>('');
const d = ref<string>('');
</script>
<template>
<div class="demo-stack">
<CfTextarea v-model="a" resize="none" placeholder="resize = none —— 完全锁定,无拖拽把手" :rows="2" />
<CfTextarea v-model="b" resize="vertical" placeholder="resize = vertical —— 仅纵向可拖(默认)" :rows="2" />
<CfTextarea v-model="c" resize="horizontal" placeholder="resize = horizontal —— 仅横向可拖" :rows="2" />
<CfTextarea v-model="d" resize="both" placeholder="resize = both —— 横纵都可拖" :rows="2" />
</div>
</template> import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
return (
<>
<CfTextarea resize="none" placeholder="resize = none" rows={2} />
<CfTextarea resize="vertical" placeholder="resize = vertical" rows={2} />
<CfTextarea resize="horizontal" placeholder="resize = horizontal" rows={2} />
<CfTextarea resize="both" placeholder="resize = both" rows={2} />
</>
);
} import { CfTextarea } from '@chufix-design/react';
export default function Demo() {
return (
<>
<CfTextarea resize="none" placeholder="resize = none" rows={2} />
<CfTextarea resize="vertical" placeholder="resize = vertical" rows={2} />
<CfTextarea resize="horizontal" placeholder="resize = horizontal" rows={2} />
<CfTextarea resize="both" placeholder="resize = both" rows={2} />
</>
);
} API
Props
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | '' | 双向绑定值;React 端用 value + onChange |
variant | 'outline' | 'filled' | 'ghost' | 'outline' | 视觉变体,与 Input 一致 |
size | 'sm' | 'md' | 'lg' | 'md' | 字号 / 内边距 |
rows | number | 3 | 初始行数 |
placeholder | string | — | 占位文案 |
disabled | boolean | false | 禁用 |
readonly | boolean | false | 只读(可选中复制,不可修改;React 端 readOnly) |
error | boolean | false | 错误状态边框 / 焦点环 |
resize | 'none' | 'vertical' | 'horizontal' | 'both' | 'vertical' | 用户拖拽 resize 行为 |
autoResize | boolean | false | 内容增减时自动调整高度(覆盖 resize) |
maxlength | number | — | 字符上限(React 端为 maxLength) |
showCount | boolean | false | 右下角显示字符计数 |
name / id 是直接透传到原生 <textarea> 的 HTML 标准属性,用于参与表单提交或 label 关联,使用方式与原生一致。
Events
| Event | 载荷类型 | 说明 |
|---|---|---|
update:modelValue | string | 输入触发,v-model 隐式监听 |
change | string | 原生 change 事件转发(失焦时) |
focus | FocusEvent | 获得焦点 |
blur | FocusEvent | 失去焦点 |
反馈与讨论
Textarea 多行输入 的讨论