Reka UI TagsInputInput 组件:标签输入框的 Props、键盘交互与源码级解析
Reka UI TagsInputInput 组件标签输入框的 Props、键盘交互与源码级解析【免费下载链接】radix-vueAn open-source UI component library for building high-quality, accessible design systems and web apps for Vue. Previously Radix Vue项目地址: https://gitcode.com/GitHub_Trending/ra/radix-vue导读TagsInputInput是 Reka UI即本仓库 radix-vue组件库源码位于 packages/core/src/TagsInput标签输入组件Tags Input中的核心文本输入部件它负责接收用户键入的标签文本并把回车添加标签、粘贴批量添加、失焦添加、Tab 添加等交互转化为根组件TagsInputRoot的标签状态更新。读完本文你将掌握TagsInputInput的每一个 Props 的含义与默认值、它与根组件上下文Context的协作方式以及Enter / Tab / Backspace / Delete / 方向键等键盘交互在源码中是如何实现的从而能在自己的 Vue 项目中正确、高效地使用并定制标签输入。定位与职责输入部件如何与根组件协作Tags Input 组件由多个部件组成TagsInputRoot容器管理标签数组状态、TagsInputItem单个标签、TagsInputItemText标签文本、TagsInputItemDelete删除按钮、TagsInputInput文本输入框以及TagsInputClear清空按钮。组件整体结构可参考文档 docs/content/docs/components/tags-input.md 中的 Anatomy 一节script setup import { TagsInputClear, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputRoot } from reka-ui /script template TagsInputRoot TagsInputItem TagsInputItemText / TagsInputItemDelete / /TagsInputItem TagsInputInput / TagsInputClear / /TagsInputRoot /template从源码结构看TagsInputInput本身不保存标签数据它通过injectTagsInputRootContext()注入根组件通过 provideTagsInputRootContext 提供的上下文Context然后调用其中的onAddValue、onInputKeydown等回调把输入事件转化为根组件的modelValue更新。这种子部件只负责输入事件采集、根组件负责状态管理的架构与 Reka UI 其他复合组件如 Combobox、Select保持一致。Props 完整说明TagsInputInput的 Props 定义位于 TagsInputInput.vue继承自PrimitiveProps共 5 个属性NameDescriptionTypeRequiredDefaultas组件要渲染成的元素或组件可被asChild覆盖。AsTag \| ComponentNoinputasChild将默认渲染元素替换为传入的子元素并合并其 props 与行为。booleanNo-autoFocus挂载时自动聚焦该元素。booleanNo-maxLength允许输入的最大字符数。numberNo-placeholder空标签输入时的占位字符。stringNo-as与asChildComposition组合能力这是 Reka UI 所有基础部件的通用能力。as默认值为input即默认渲染一个原生input通过as可改渲染成其他标签或组件通过asChild则可以把自定义子元素作为实际渲染节点例如用无样式的input子元素包裹自定义图标。这一机制在 Primitive 中实现细节可参考仓库文档 docs/content/docs/guides 下的 Composition 指南。autoFocus挂载后自动聚焦源码中autoFocus在onMounted钩子里实现TagsInputInput.vue先查找实际渲染的input节点考虑到asChild场景然后通过setTimeout(..., 1)延迟一个宏任务确保 DOM 完全刷新后再调用inputEl.focus()onMounted(() { const inputEl currentElement.value.nodeName INPUT ? currentElement.value : currentElement.value.querySelector(input) if (!inputEl) return setTimeout(() { // make sure all DOM was flush then only capture the focus if (props.autoFocus) inputEl?.focus() }, 1) })maxLength单次输入长度上限直接透传给原生input的maxlength属性模板中:maxlengthmaxLength。注意它与根组件的max标签总数上限是两个不同的维度maxLength限制正在输入的文本长度max限制已添加的标签数量。placeholder空输入提示透传给原生input的placeholder。仓库中的示例用法见 TagsInput/story/_TagsInput.vueTagsInputInput placeholderAnything... classfocus:outline-none flex-1 rounded bg-transparent text-white placeholder:text-mauve10 px-1 /数据属性Data AttributesTagsInputInput会向渲染节点输出以下数据属性便于样式定制与测试AttributeValues[data-invalid]Present when input value is invalid当输入重复标签或超过max上限时根组件会把isInvalidInput置为trueTagsInputInput的模板中对应渲染:data-invalidcontext.isInvalidInput.value ? : undefinedTagsInputInput.vue。搭配 CSS 选择器[data-invalid]即可实现输入非法值的红色描边等反馈。输入交互的源码级解析TagsInputInput的核心价值在于它把 5 类输入事件与根组件的标签管理逻辑挂钩模板绑定见 TagsInputInput.vue。Enter 回车添加标签keydown.enterhandleCustomKeydown在按下回车时调用。handleCustomKeydownTagsInputInput.vue的逻辑若正处于输入法组合isComposing阶段则跳过避免拼音/日文输入法候选选中干扰await nextTick()后检查event.defaultPrevented——若用户自定义了keydown.enter.prevent则尊重用户逻辑不再自动添加输入值为空则直接返回调用context.onAddValue(target.value)尝试添加成功返回true后清空输入框event.preventDefault()阻止默认行为避免组件处于form中时触发表单提交。Tab 添加标签keydown.tabhandleTab当根组件开启addOnTab时Tab 键行为与回车一致调用同一个handleCustomKeydown否则走原生 Tab 焦点切换TagsInputInput.vue。Blur 失焦添加blurhandleBlurTagsInputInput.vue在根组件开启addOnBlur时生效且有两处防御逻辑先清除当前选中的标签selectedElement如果失焦是因为点击了下拉内容如与 Combobox 组合时的候选项导致通过aria-controls与relatedTarget.closest判断则不触发添加——因为被点击的候选项应作为新标签添加而不是把输入框当前值添加进去输入为空则直接返回。Paste 粘贴批量添加pastehandlePasteTagsInputInput.vue在根组件开启addOnPaste时阻止默认粘贴行为读取剪贴板文本并用delimiter分隔符切分后逐段调用onAddValue批量添加标签。例如粘贴vue,react,svelte在默认逗号分隔符下会一次生成三个标签。Delimiter 分隔符即时触发inputhandleInputTagsInputInput.vue监听每次输入若当前输入字符匹配delimiter支持字符串或正则先把该字符从输入值中剔除再尝试把前面已输入的内容作为标签添加。这样用户输入vue,时vue会立即成为标签而逗号不会残留在输入框里。输入法组合期间该逻辑同样被跳过。方向键与删除键标签键盘导航keydownhandleInputKeydown把键盘事件转发给根组件的onInputKeydownTagsInputRoot.vue实现了完整的标签键盘导航Backspace光标位于输入框首位时先选中最后一个标签若已有选中标签则删除它并把选中态移到左侧标签左无标签则回到输入框Delete标签处于激活态时删除当前标签并把激活态移到右侧标签ArrowLeft光标在首位时选中上一个标签RTL 下方向反转ArrowRight在最后一个标签上按右方向键则取消选中、回到输入框Home/End激活第一个 / 最后一个标签。这些行为与文档 docs/content/docs/components/tags-input.md 的 Keyboard Interactions 一节描述的键位一一对应。仓库测试 TagsInput.test.ts 中覆盖了回车添加标签后清空输入框、addTag事件发出、ArrowLeft 选中标签、data-state 在 active/inactive 间切换等行为可当作行为契约参考。与根组件 Props 的联动要点TagsInputInput的行为受根组件TagsInputRoot若干 Props 驱动使用时应组合配置完整参数见 TagsInputRoot.vue 与 docs/content/meta/TagsInputRoot.mdRoot 参数类型默认值对 Input 的影响addOnBlurboolean-失焦时把输入框内容添加为标签addOnPasteboolean-粘贴时按分隔符切分并批量添加addOnTabboolean-Tab 键等同回车添加标签delimiterstring \| RegExp,输入/粘贴时的分隔触发与切分规则disabledboolean-禁用输入框透传disabled并输出data-invalid相关状态duplicateboolean-允许重复标签否则重复输入会被判定为 invalidmaxnumber0标签数量上限0表示不限超限触发invalid事件convertValue(value: string) T-使用对象作标签值时把输入字符串转换为对象必填displayValue(value: T) stringvalue.toString()自定义标签显示文本modelValue/defaultValueT[][]受控 / 非受控的标签数组典型组合示例粘贴自动添加来自文档 docs/content/docs/components/tags-input.md 的 Paste behavior 示例script setup langts import { TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputRoot } from reka-ui /script template TagsInputRoot v-modelmodelValue add-on-paste … /TagsInputRoot /template多分隔符正则来自文档的 Multiple delimiters 示例逗号、分号、空格、制表符、换行均可触发添加script setup langts import { TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputRoot } from reka-ui // split by space, comma, semicolon, tab, or newline const delimiter /[ ,;\t\n\r]/ /script template TagsInputRoot v-modelmodelValue :delimiterdelimiter add-on-paste … /TagsInputRoot /template对象标签值当标签值是对象时参考 story 目录下的 TagsInputObject.story.vue必须同时提供convertValue把输入字符串转成对象与displayValue把对象渲染成可读文本否则根组件会抛出错误You must provide a convertValue function when using objects as values.见 TagsInputRoot.vue。键盘交互一览TagsInputInput聚焦时支持的完整键盘操作对应 docs/content/docs/components/tags-input.md 的 Accessibility 章节按键行为Enter把当前输入内容添加为标签输入法组合期间忽略Tab开启addOnTab时等同回车添加Backspace光标在首位时先选中最后一个标签标签激活时删除并激活左侧标签Delete标签激活时删除当前标签并激活右侧标签ArrowLeft/ArrowRight在标签间移动激活态RTL 方向自动反转最后一个标签上按右方向回到输入框Home/End激活第一个 / 最后一个标签总结TagsInputInput是 Reka UI Tags Input 的输入入口它自身只负责事件采集与转发通过 Context 把回车、Tab、失焦、粘贴、分隔符输入、方向键等交互交给根组件TagsInputRoot统一处理标签状态。实际使用时请记住三组关键配置添加时机addOnTab/addOnBlur/addOnPaste三个布尔 Props 控制何时把输入内容转为标签分隔规则delimiter字符串或正则同时作用于输入即时触发与粘贴批量切分约束校验maxLength限制单次输入长度根组件的max限制标签总数duplicate控制是否允许重复非法输入会通过[data-invalid]与invalid事件暴露给开发者。深入源码可继续阅读 TagsInputInput.vue、TagsInputRoot.vue 以及行为测试 TagsInput.test.ts或参考完整组件文档 docs/content/docs/components/tags-input.md。【免费下载链接】radix-vueAn open-source UI component library for building high-quality, accessible design systems and web apps for Vue. Previously Radix Vue项目地址: https://gitcode.com/GitHub_Trending/ra/radix-vue创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考