
radix-vue Autocomplete 组件完全指南自由文本输入与智能提示的原生实现【免费下载链接】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导读Autocomplete 是 radix-vue现 Reka UI提供的一款带建议的自由文本输入框组件用户可以随意输入任意文本组件在下方弹出建议列表供参考与快捷填充但不强制用户从列表中选取——这正是它与 Combobox 的本质区别。本文基于仓库中的官方文档 autocomplete.md结合源码 AutocompleteRoot.vue、AutocompleteInput.vue 与测试用例 Autocomplete.test.ts完整讲解其组件结构、与 Combobox 的差异、全部 API、实战示例、键盘交互与无障碍实现读完即可在项目中落地一个可搜索、可自由输入、支持分组与虚拟滚动的自动补全输入框。Autocomplete 是什么Autocomplete 是 radix-vue 家族中面向搜索补全场景的输入类组件当前标记为Alpha阶段。它的核心模型是modelValue就是输入框里的文本本身string而不是被选中的某个列表项。这意味着它天然适合搜索框、标签输入、地点联想、命令面板等允许用户自由发挥的场景列表只是助手输入才是主角。官方特性列表来自 autocomplete.md支持受控controlled与非受控uncontrolled两种模式提供inline与popper两种定位模式支持 item条目、label标签、group条目分组焦点完全托管fully managed完整的键盘导航支持自定义占位符placeholder支持从右到左RTL的阅读方向自由文本输入——value 是用户敲进去的文本而不是一次选择。安装Autocomplete 随 reka-uiradix-vue 的继任包名一起分发无需单独安装npm install reka-ui # 或 pnpm add reka-ui / yarn add reka-uiAnatomy组件解剖Autocomplete 是全组件拼装式设计composition-based所有部件可以按需组合。官方给出的标准结构如下script setup langts import { AutocompleteAnchor, AutocompleteArrow, AutocompleteCancel, AutocompleteContent, AutocompleteEmpty, AutocompleteGroup, AutocompleteInput, AutocompleteItem, AutocompleteLabel, AutocompletePortal, AutocompleteRoot, AutocompleteSeparator, AutocompleteTrigger, AutocompleteViewport, } from reka-ui /script template AutocompleteRoot AutocompleteAnchor AutocompleteInput / AutocompleteTrigger / AutocompleteCancel / /AutocompleteAnchor AutocompletePortal AutocompleteContent AutocompleteViewport AutocompleteEmpty / AutocompleteItem / AutocompleteSeparator / AutocompleteGroup AutocompleteLabel / AutocompleteItem / /AutocompleteGroup /AutocompleteViewport AutocompleteArrow / /AutocompleteContent /AutocompletePortal /AutocompleteRoot /template各部件职责一览部件作用AutocompleteRoot容器持有 open / modelValue / disabled / 过滤等全部状态AutocompleteAnchor锚点当 Content 使用popper定位时作为定位参照AutocompleteInput搜索输入框键入即实时更新modelValueAutocompleteTrigger切换下拉内容开合的按钮AutocompleteCancel清空输入文本并重置 value 的按钮AutocompleteEmpty当没有条目匹配查询时展示的空状态AutocompletePortal将 Content 传送到body下渲染AutocompleteContent打开时弹出的下拉面板AutocompleteViewport容纳所有条目的滚动容器AutocompleteItem建议条目被选中后其文本值填充输入框AutocompleteGroup/AutocompleteLabel条目分组与组标签自动实现无障碍标注AutocompleteSeparator条目间的视觉分隔线AutocompleteArrow指向触发器的可选箭头仅popper模式可用AutocompleteVirtualizer虚拟滚动容器用于长列表性能优化Autocomplete vs. Combobox选型对照Autocomplete 与 Combobox 极其相似关键差异在文档中有张清晰的对照表AutocompleteComboboxmodelValue输入文本string被选中的条目AcceptableValue自由文本支持——任意文本都合法不支持——必须从列表中选择multiple不支持支持失焦时的输入默认保留用户输入的文本默认重置为已选值条目选择行为用条目文本填充输入框将modelValue设为条目的 value何时用哪个需要可以随便输入、列表只是建议时用 Autocomplete需要必须从预定义集合中挑选时用 Combobox。从源码层面看这个差异落在 AutocompleteRoot.vue它的modelValue是Refstring并且用一个可写计算属性contextModelValue把 Combobox 上下文里的任意值强制字符串化null/undefined归为其余String(val)从而复用 Combobox 的全部子部件但语义上始终是文本。API Reference以下 Props / Events / Slots 数据来源于仓库自动生成的元数据文件与运行时完全一致。AutocompleteRoot根组件包含 Autocomplete 的全部部件。默认渲染为divas/asChild可覆盖。Props名称类型默认值说明modelValuestring—受控值输入文本可用v-model绑定defaultValuestring—初始渲染时的非受控值openboolean—受控开合状态可用v-model:opendefaultOpenboolean—初始开合状态非受控disabledboolean—为true时禁止用户交互dirltr \| rtl—阅读方向缺省时继承全局配置并假定 LTRnamestring—表单字段名随所属表单以 name/value 对提交requiredboolean—为true时提交前必须设置值resetSearchTermOnBlurbooleanfalse输入框失焦时是否重置内部搜索词openOnFocusbooleanfalse输入框聚焦时是否自动打开openOnClickbooleanfalse点击输入框时是否自动打开ignoreFilterboolean—为true时关闭默认过滤逻辑highlightOnHoverbooleantrue悬停条目是否触发高亮asAsTag \| Componentdiv渲染为的元素/组件asChildboolean—将行为合并到子元素上源码佐证以上默认值在 AutocompleteRoot.vue 的withDefaults中逐一声明。Events名称类型说明update:modelValue[value: string]值变化时触发update:open[value: boolean]开合状态变化时触发highlight[{ ref: HTMLElement, value: string }]高亮条目变化时触发Slots名称类型说明openboolean当前开合状态modelValuestring当前活跃值AutocompleteInput搜索输入框键入内容会实时更新modelValue。默认渲染为input。名称类型默认值说明modelValuestring—受控过滤词可用v-modelautoFocusboolean—挂载时自动聚焦disabledboolean—禁止交互asAsTag \| Componentinput渲染元素它内部基于ListboxFilter实现见 AutocompleteInput.vue自动附加了rolecombobox、aria-expanded、aria-autocompletelist、autocompleteoff等无障碍属性并托管input/focus/click/keydown/composition事件。AutocompleteContent打开时弹出的面板。可通过position选择两种定位模式inline默认用 CSS 控制位置popper与 Popover / DropdownMenu 相同的浮动定位此时应搭配AutocompleteAnchor作为锚点。完整 Props 与 Combobox 的 Content 完全一致side、align、sideOffset、alignOffset、avoidCollisions、collisionBoundary、collisionPadding、sticky、forceMount、hideWhenEmpty、bodyLock等详见元数据 ComboboxContent.md。其中两个与本组件强相关的点hideWhenEmpty无匹配条目时隐藏菜单由于组件基于 Presence 机制渲染Content 默认是挂载于 DOM 的用于进出场动画这一点与 Presence 机制 相关文档以PresenceCallout /专门提醒。Content 上暴露的数据属性属性值[data-state]open/closed[data-side]left/right/bottom/top[data-align]start/end/center[data-empty]无匹配过滤结果时存在在popper模式下还会注入以下 CSS 变量供动画/样式使用CSS 变量含义--reka-combobox-content-transform-origin由内容与箭头位置/偏移计算出的transform-origin--reka-combobox-content-available-width触发器到边界之间剩余宽度--reka-combobox-content-available-height触发器到边界之间剩余高度--reka-combobox-trigger-width触发器宽度--reka-combobox-trigger-height触发器高度说明这些变量复用了 Combobox 的命名空间--reka-combobox-*因为 Autocomplete 在内部复用了 Combobox 的定位上下文见 AutocompleteRoot.vue 中的provideComboboxRootContext。AutocompleteItem建议条目。被选中时其字符串值会填充到输入框注意不是设置modelValue为对象值而是把文本写进输入。Props 与 ComboboxItem 一致名称类型说明valueT必填条目的值disabledboolean禁用条目textValuestring条目内容的纯文本表示当 children 不是纯文本时必须提供用于过滤数据属性属性值[data-state]checked/unchecked[data-highlighted]高亮时存在[data-disabled]禁用时存在其他部件AutocompleteAnchorpositionpopper时的定位锚点。AutocompleteTrigger开合按钮暴露[data-state]open/closed与[data-disabled]。AutocompleteCancel清空输入并重置值。AutocompleteEmpty无匹配时的空状态占位。AutocompletePortal把 Content 传送到body此时 Content 需设positionpopper才能自动计算位置类似 Popover / DropdownMenu。AutocompleteViewport滚动容器。AutocompleteGroup / AutocompleteLabel分组与自动无障碍标注的组标签Label 不可用方向键聚焦。AutocompleteSeparator视觉分隔线。AutocompleteArrow仅popper模式可用必须渲染在 Content 内部。AutocompleteVirtualizer虚拟滚动容器长列表性能优化通用机制见虚拟化指南。实战示例基本用法搜索水果modelValue是字符串反映用户键入的任意内容选择条目则把该条目的文本填入输入框script setup langts import { AutocompleteContent, AutocompleteInput, AutocompleteItem, AutocompletePortal, AutocompleteRoot } from reka-ui import { ref } from vue const searchText ref() const fruits [Apple, Banana, Orange, Grapes, Pineapple] /script template AutocompleteRoot v-modelsearchText AutocompleteInput placeholderType a fruit... / AutocompletePortal AutocompleteContent AutocompleteItem v-forfruit in fruits :keyfruit :valuefruit {{ fruit }} /AutocompleteItem /AutocompleteContent /AutocompletePortal /AutocompleteRoot /template无匹配时隐藏菜单给AutocompleteContent加hideWhenEmptytemplate AutocompleteRoot v-modelsearchText AutocompleteInput placeholderType a fruit... / AutocompletePortal AutocompleteContent hide-when-empty AutocompleteItem v-forfruit in fruits :keyfruit :valuefruit {{ fruit }} /AutocompleteItem /AutocompleteContent /AutocompletePortal /AutocompleteRoot /template表单提交Autocomplete 的值会作为普通文本字段随表单提交测试用例 Autocomplete.test.ts 验证了隐藏 input 与提交行为script setup langts import { AutocompleteContent, AutocompleteInput, AutocompleteItem, AutocompletePortal, AutocompleteRoot } from reka-ui import { ref } from vue const query ref() const cities [New York, Los Angeles, Chicago, Houston, Phoenix] /script template form AutocompleteRoot v-modelquery namecity AutocompleteInput placeholderEnter a city... / AutocompletePortal AutocompleteContent AutocompleteItem v-forcity in cities :keycity :valuecity {{ city }} /AutocompleteItem /AutocompleteContent /AutocompletePortal /AutocompleteRoot /form /template完整的分组 触发按钮 清空按钮示例仓库 demoAutocomplete/tailwind/index.vue给出了带 Anchor、Trigger、分组、分隔线、空状态与 Tailwind 样式的完整形态核心骨架如下AutocompleteRoot v-modelv classrelative AutocompleteAnchor class...border... AutocompleteInput placeholderType or select an option... / AutocompleteTrigger Icon iconradix-icons:chevron-down / /AutocompleteTrigger /AutocompleteAnchor AutocompleteContent classabsolute z-10 w-full mt-1 ... AutocompleteViewport AutocompleteEmpty class... / template v-for(group, index) in options :keygroup.name AutocompleteGroup AutocompleteSeparator v-ifindex ! 0 / AutocompleteLabel{{ group.name }}/AutocompleteLabel AutocompleteItem v-foroption in group.children :keyoption.name :valueoption.name {{ option.name }} /AutocompleteItem /AutocompleteGroup /template /AutocompleteViewport /AutocompleteContent /AutocompleteRoot注意其中 Content 使用了absolute w-full的内联定位模式inline配合data-[side*]动画类即可实现简洁的紧贴输入框下拉效果CSS 版 demo 见 Autocomplete/css/index.vue。无障碍与键盘交互Autocomplete 遵循 Combobox WAI-ARIA 设计模式文档 frontmatter 中的aria字段即声明了这一点测试中用 axe 校验无违规见 Autocomplete.test.ts。键盘交互表按键行为Enter焦点在AutocompleteItem上时选中该条目并用其值填充输入框ArrowDown焦点在AutocompleteInput上时打开下拉焦点在条目上时移到下一个条目ArrowUp焦点在AutocompleteInput上时打开下拉焦点在条目上时移到上一个条目Esc关闭下拉并把焦点还给AutocompleteInput从源码理解实现原理内部借用 Combobox 的骨架Autocomplete 并非从零实现而是在 AutocompleteRoot.vue 中组合了PopperRootListboxRoot并通过provideComboboxRootContext注入 Combobox 上下文从而直接复用 Combobox 的 Content/Item/Group/Portal 等全部子部件multiple被固定为false。过滤逻辑过滤状态由filterState计算属性集中管理AutocompleteRoot.vue遍历allItems用useFilter({ sensitivity: base })的大小写不敏感包含匹配打分并同步维护过滤后的组集合组内任一成员命中即保留该组。当ignoreFilter或虚拟滚动开启时跳过过滤。这正是data-empty、AutocompleteEmpty、hideWhenEmpty的行为来源。输入即值typing-as-valueAutocompleteInput.vue 的processInputValue是核心每次 input 事件都把输入框文本同时写入rootContext.filterSearch用于过滤列表与autocompleteContext.modelValue组件的值输入框失焦时默认resetSearchTermOnBlurfalse内部搜索词会重置但用户输入的文本作为 value 被保留——测试 Autocomplete.test.ts 明确断言了这一点。IME 输入法兼容输入框对 IME 合成composition做了细致处理AutocompleteInput.vue合成期间不吞方向键、不触发过滤、不更新modelValue待compositionend后统一提交Android 软键盘的纯文本autocorrect合成则特殊处理为实时过滤。测试用例覆盖了桌面拼音预编辑、Android 软键盘、CJK IME中文/日文等多种场景Autocomplete.test.ts。小结选型允许自由输入 → Autocomplete必须从集合中选 → Combobox核心modelValue即输入文本条目选择只是把文本填进输入框结构全部件拼装可自由裁剪positioninline用 CSS 定位popper用浮动定位增强点hideWhenEmpty控制空态、openOnFocus/openOnClick控制唤起时机、ignoreFilter关闭内置过滤、Virtualizer支持万级长列表无障碍遵循 WAI-ARIA Combobox 模式键盘全托管且对中文等 IME 输入有专门兼容。官方文档与源码入口组件文档 autocomplete.md、根实现 AutocompleteRoot.vue、输入实现 AutocompleteInput.vue、测试 Autocomplete.test.ts、完整 Demo Autocomplete/tailwind/index.vue。【免费下载链接】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),仅供参考