news 2026/9/24 16:31:43

shadcn-vue Textarea 组件完全指南:安装、属性解析与表单集成实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
shadcn-vue Textarea 组件完全指南:安装、属性解析与表单集成实战

shadcn-vue Textarea 组件完全指南:安装、属性解析与表单集成实战

【免费下载链接】shadcn-vueVue port of shadcn-ui项目地址: https://gitcode.com/gh_mirrors/sh/shadcn-vue

导读

Textarea 是 shadcn-vue 中用于展示多行文本输入的表单组件,它在原生<textarea>之上封装了完整的主题样式与受控值绑定能力,开箱即用地支持占位符、禁用态、焦点环以及 v-model 双向绑定。本文以 textarea.md 为骨架,结合仓库中defaultnew-york两套风格的源码实现,完整讲解安装方式、核心 API、六种常用场景的示例代码,并深入剖析其基于useVModel的受控原理与配合 vee-validate 表单校验的落地写法。

Textarea 是什么

Textarea 组件是对原生<textarea>元素的样式化封装,核心目标有两个:

  1. 统一样式:通过 Tailwind CSS 类组合出与 shadcn-vue 其他表单组件(Input、Select 等)一致的视觉体系;
  2. 简化受控逻辑:通过modelValue/update:modelValue实现 Vue 标准的v-model双向绑定,无需开发者手动维护value事件。

在仓库中,Textarea 的组件源码位于 Textarea.vue(default 风格)与 Textarea.vue(new-york 风格),两套实现的脚本逻辑完全相同,仅样式类存在差异。配套的示例代码位于 examples 目录 下,覆盖文档中列出的全部场景。

安装

文档提供了两种安装方式:CLI 自动安装与手动复制。

方式一:CLI 安装(推荐)

在项目根目录执行:

npx shadcn-vue@latest add textarea

该命令会自动完成依赖安装、组件文件生成与路径别名配置。shadcn-vue 的 CLI 是 Vue 生态中 shadcn-ui 的命令行实现,add子命令会从组件注册表拉取 Textarea 组件及其依赖。

方式二:手动安装

手动安装分两步:

第一步,安装运行依赖:

npm install reka-ui

从源码 Textarea.vue 可以看到,Textarea 实际还依赖@vueuse/core(提供useVModel)与项目内的cn工具函数(通常位于src/lib/utils.ts),因此完整的依赖还包括:

npm install reka-ui @vueuse/core

同时需要保证项目中存在基于clsxtailwind-mergecn工具函数(cn用于合并默认样式与外部传入的class)。

第二步,复制组件代码:

将 Textarea.vue 复制到项目的src/components/ui/textarea/Textarea.vue,并确认路径别名@指向src(Vite 或 Nuxt 配置中通常已定义)。

基本用法

安装完成后,在组件中按如下方式引入使用:

<script setup lang="ts"> import { Textarea } from '@/components/ui/textarea' </script> <template> <Textarea /> </template>

Textarea支持原生<textarea>的全部标准属性,包括placeholderdisabledidrowsmaxlength等,均会透传到内部的原生元素上。

组件 API 与源码解析

完整阅读 Textarea.vue 的<script setup>部分,可以提炼出该组件的完整公开 API:

Props

Prop类型说明
classHTMLAttributes["class"]追加到组件根元素上的自定义样式类,经cn合并
modelValuestring \| numberv-model绑定的值
defaultValuestring \| number非受控模式下的初始默认值

Emits

事件载荷类型说明
update:modelValuestring \| numberv-model更新事件

受控绑定原理

源码中的关键逻辑是useVModel的使用:

const modelValue = useVModel(props, "modelValue", emits, { passive: true, defaultValue: props.defaultValue, })

这是@vueuse/core提供的v-model封装,其作用:

  • 双向绑定:内部v-model="modelValue"直接绑定到原生<textarea>,用户输入会自动触发update:modelValue事件,实现与props.modelValue的同步;
  • 受控/非受控双模式:当外部传入modelValue时为受控模式;未传入时回退到defaultValue,成为非受控组件,与 React 生态中 defaultValue 的设计思路一致;
  • passive 优化passive: true表示组件不会在外部主动同步 props,而是依赖 Vue 的响应式系统,减少不必要的性能开销。

两套风格差异

对比 default 版 与 new-york 版 的类名,可以看到:

  • defaultmin-h-20(80px 最小高度)、bg-background(不透明背景)、focus-visible:ring-2(双层焦点环);
  • new-yorkmin-h-[60px](60px 最小高度)、bg-transparent(透明背景)、focus-visible:ring-1(单层焦点环)并附带shadow-sm

两套风格共享的基础样式包括flex w-full rounded-md border border-input px-3 py-2 text-sm placeholder:text-muted-foreground以及禁用态样式disabled:cursor-not-allowed disabled:opacity-50。选择哪套风格取决于你初始化项目时指定的样式选项,可在 shadcn-vue 初始化时配置。

示例详解

文档列出的六个示例在仓库中均有完整实现,以下逐一讲解。

默认示例(Default)

源码:TextareaDemo.vue

<script setup lang="ts"> import { Textarea } from "@/registry/default/ui/textarea" </script> <template> <Textarea placeholder="Type your message here." /> </template>

最基础的用法,仅通过placeholder属性给出输入提示文案。

禁用态(Disabled)

源码:TextareaDisabled.vue

<template> <Textarea placeholder="Type your message here." disabled /> </template>

通过原生disabled属性禁用输入。从源码类名disabled:cursor-not-allowed disabled:opacity-50可知,禁用态会自动呈现不可点击光标并降低 50% 透明度。

带标签(With Label)

源码:TextareaWithLabel.vue

<template> <div class="grid w-full gap-1.5"> <Label for="message">Your message</Label> <Textarea id="message" placeholder="Type your message here." /> </div> </template>

配合 shadcn-vue 的 Label 组件使用。关键在于LabelforTextareaid必须一致,点击标签文本即可聚焦输入框,这也是无障碍(a11y)的最佳实践。

带说明文本(With Text)

源码:TextareaWithText.vue

<template> <div class="grid w-full gap-1.5"> <Label for="message-2">Your message</Label> <Textarea id="message-2" placeholder="Type your message here." /> <p class="text-sm text-muted-foreground"> Your message will be copied to the support team. </p> </div> </template>

在标签与输入框下方追加一段辅助说明文字,使用text-sm text-muted-foreground样式呈现为弱化的次级文案,适合描述输入规则或用途。

带按钮(With Button)

源码:TextareaWithButton.vue

<template> <div class="grid w-full gap-2"> <Textarea placeholder="Type your message here." /> <Button>Send message</Button> </div> </template>

典型的"输入 + 提交"组合布局,常用于消息发送、评论表单等场景。注意这里 Button 未显式设置type,在实际表单中如需提交应写为type="submit"

表单集成(Form)

源码:TextareaForm.vue(new-york 风格同款见 TextareaForm.vue)

这是最完整的实战示例,演示了 Textarea 与vee-validate + zod的深度集成:

<script setup lang="ts"> import { toTypedSchema } from "@vee-validate/zod" import { useForm } from "vee-validate" import { h } from "vue" import * as z from "zod" import { Button } from "@/registry/default/ui/button" import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/registry/default/ui/form" import { Textarea } from "@/registry/default/ui/textarea" import { toast } from "@/registry/default/ui/toast" const formSchema = toTypedSchema(z.object({ bio: z .string() .min(10, { message: "Bio must be at least 10 characters." }) .max(160, { message: "Bio must not be longer than 30 characters." }), })) const { handleSubmit } = useForm({ validationSchema: formSchema }) const onSubmit = handleSubmit((values) => { toast({ title: "You submitted the following values:", description: h("pre", { class: "mt-2 w-[340px] rounded-md bg-slate-950 p-4" }, h("code", { class: "text-white" }, JSON.stringify(values, null, 2))), }) }) </script> <template> <form class="w-full space-y-6" @submit="onSubmit"> <FormField v-slot="{ componentField }" name="bio"> <FormItem> <FormLabel>Bio</FormLabel> <FormControl> <Textarea placeholder="Tell us a little bit about yourself" class="resize-none" v-bind="componentField" /> </FormControl> <FormDescription> You can <span>@mention</span> other users and organizations. </FormDescription> <FormMessage /> </FormItem> </FormField> <Button type="submit"> Submit </Button> </form> </template>

该示例的关键要点:

  1. zod schema 定义校验规则bio字段要求 10~160 个字符,toTypedSchema将 zod schema 转换为 vee-validate 的类型化 schema;
  2. v-bind="componentField"打通表单绑定FormField提供的componentField包含了modelValueonUpdate:modelValue等事件,通过v-bind一次性透传给 Textarea,无需手动编写绑定代码;
  3. resize-none禁用拖拽缩放:给class传入 Tailwind 类即可覆盖默认样式,体现了cn合并机制的灵活性;
  4. 完整表单反馈FormDescription展示辅助说明,FormMessage自动渲染校验错误信息,toast展示提交结果。

整个流程清晰展示了 Textarea 在真实表单场景中的标准姿势:FormField负责取字段状态,FormControl包裹控件,componentField完成值绑定,错误信息由FormMessage自动呈现。

样式定制建议

Textarea 的默认样式通过cn()props.class合并,因此自定义样式有两种途径:

  1. 直接传class:如示例中的class="resize-none",追加的 Tailwind 类会覆盖同属性默认值(tailwind-merge保证后传入的类优先);
  2. 修改组件源码:直接编辑 Textarea.vue 中的默认类名,例如调整最小高度min-h-20、圆角rounded-md或焦点环样式。

若想全局统一调整 Textarea 风格,建议通过修改components/ui/textarea/Textarea.vue并配合设计系统的 CSS 变量(如--input--ring--background--muted-foreground)实现主题联动。

小结

Textarea 组件虽然代码量不大,但集中体现了 shadcn-vue 的设计哲学:样式与逻辑分离、开箱即用的受控绑定、以及与表单体系的平滑集成。掌握本文内容后,你可以:

  • 通过 CLI 或手动方式快速集成 Textarea 组件;
  • 理解modelValue/defaultValue/class三个核心属性及useVModel的底层绑定原理;
  • 灵活组合 Label、Button、Form 等组件搭建完整的多行文本输入场景;
  • 使用 vee-validate + zod 为多行文本添加校验逻辑。

如需进一步了解相关组件,可继续阅读 input.md、form.md 与 label.md 等文档。

【免费下载链接】shadcn-vueVue port of shadcn-ui项目地址: https://gitcode.com/gh_mirrors/sh/shadcn-vue

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 16:31:21

palera1n:A8 到 A11 设备 iOS 15 越狱的 checkm8 完整指南

palera1n&#xff1a;A8 到 A11 设备 iOS 15 越狱的 checkm8 完整指南 【免费下载链接】palera1n Jailbreak for A8 through A11, T2 devices, on iOS/iPadOS/tvOS 15.0, bridgeOS 5.0 and higher. 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n palera1n…

作者头像 李华
网站建设 2026/9/24 16:24:04

智慧社区建设踩坑记:这3件事千万别做

智慧社区建设踩坑记&#xff1a;这3件事千万别做 干这些年&#xff0c;见过太多智慧社区项目&#xff0c;宣传时都是"标杆"“示范”&#xff0c;落地后却成了摆设&#xff1a;大屏关着吃灰&#xff0c;平台没人登录&#xff0c;居民该跑腿还跑腿。踩坑的社区不少&…

作者头像 李华
网站建设 2026/9/24 16:18:37

【Coze】【图文】人间清醒大学男生工作流

今天给大家演示一个 Coze 图文工作流 ——「人间清醒大学男生」的完整流程。该工作流通过文字生成与图像生成的结合,把用户输入转化为“人间清醒”风格的简短文案,并进一步扩展成阳光明亮、治愈系风格的插画,主角是一位在校大学男生。最终成果不仅仅是简单的文字,而是图文并…

作者头像 李华