Editable 组件完全指南:内联编辑、受控模式与键盘无障碍实现)
reka-uiRadix VueEditable 组件完全指南内联编辑、受控模式与键盘无障碍实现【免费下载链接】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导读Editable 是 reka-ui即 Radix VueVue 版无头 UI 组件库中用于单行文本就地编辑的组件页面加载时它以静态文本Preview形式渲染触发编辑交互后切换为文本输入框Input并支持提交、取消、激活模式等完整的状态控制。本文基于 editable.md 官方文档结合 Editable 源码目录 与自动化测试系统讲解其七个组成部件、全部 Props/Events/Slots/Methods、受控与非受控用法、键盘交互以及底层状态机实现帮助你在 Vue 项目中快速落地点击即编辑的高可用表单体验。一、组件定位与核心特性Editable 解决的是静态展示 ↔ 编辑输入的无缝切换问题默认情况下它以静态文本呈现适合列表、表格等只读为主的场景当用户执行预设的交互聚焦或双击后变为输入框编辑完成后通过提交或取消回到静态态。官方文档归纳了三大特性Full keyboard navigation完整键盘导航聚焦、提交、取消均可通过键盘完成Can be controlled or uncontrolled同时支持受控modelValue与非受控defaultValue两种用法Focus is fully managed焦点完全由组件托管进入编辑模式时自动聚焦输入框。二、安装从命令行安装组件包npm install reka-uireka-ui 是这个项目的发布包名该项目即 Radix Vue 的新命名。安装后在 Vue 组件中直接按需导入即可。三、Anatomy七个部件的组合结构将全部部件导入并拼装成完整结构script setup import { EditableArea, EditableCancelTrigger, EditableEditTrigger, EditableInput, EditablePreview, EditableRoot, EditableSubmitTrigger } from reka-ui /script template EditableRoot EditableArea EditablePreview / EditableInput / /EditableArea EditableEditTrigger / EditableSubmitTrigger / EditableCancelTrigger / /EditableRoot /template各部件职责与默认渲染元素依据源码packages/core/src/Editable/下各文件确认部件默认元素职责EditableRootdiv根容器持有全部状态与上下文EditableAreadiv包裹文本部分Preview Input承载数据属性EditablePreviewspan静态文本展示可设置tabindex0参与焦点导航EditableInputinput编辑态输入框管理焦点、按键提交/取消EditableEditTriggerbutton进入编辑模式的触发按钮EditableSubmitTriggerbutton提交当前值的触发按钮EditableCancelTriggerbutton取消编辑的触发按钮除EditableRoot外的所有部件都支持as/asChild属性PrimitiveProps可改写为任意元素或组件便于与自己的按钮、图标组件组合。四、API ReferenceRoot 核心 API4.1 PropsEditableRoot通过 EditableRoot.vue 的EditableRootProps接口定义继承PrimitiveProps与FormFieldProps完整参数如下名称类型默认值说明activationModedblclick \| focus \| nonefocus进入编辑模式的触发事件asAsTag \| Componentdiv渲染为的元素可被asChild覆盖asChildboolean-将默认渲染元素替换为子元素并合并 props 与行为autoResizebooleanfalse是否自动调整尺寸隐藏式同网格覆盖实现defaultValuestring-非受控模式下的默认值dirltr \| rtl-阅读方向缺省时继承ConfigProvider否则假设 LTRdisabledbooleanfalse是否禁用idstring-字段 idmaxLengthnumber-允许输入的最大字符数modelValuestring \| null-受控模式下的值namestring-字段名随所属表单以 name/value 形式提交placeholderstring \| { edit: string; preview: string }Enter text...占位符可分别指定编辑态与预览态文本readonlyboolean-是否只读requiredbooleanfalse为true时提交所属表单前用户必须设置值selectOnFocusbooleanfalse聚焦时是否选中输入框内全部文本startWithEditModeboolean-初始是否直接处于编辑模式submitModeblur \| none \| enter \| bothblur提交触发方式失焦 / 仅手动 / 回车 / 两者源码中withDefaults确认了默认值集合EditableRoot.vueas: div、disabled: false、submitMode: blur、activationMode: focus、selectOnFocus: false、placeholder: Enter text...、autoResize: false、required: false。4.2 Events名称参数说明submit[value: string \| null]提交值时的回调update:modelValue[value: string]值变化时触发v-modelupdate:state[state: cancel \| submit \| edit]编辑状态变化时触发4.3 Slots默认插槽暴露如下作用域属性便于自定义内部结构与样式名称类型说明isEditingboolean是否处于编辑模式modelValuestring \| null \| undefined当前值isEmptyboolean是否为空submit() void提交值的函数cancel() void取消编辑的函数edit() void进入编辑模式的函数4.4 Methods通过 ref 调用名称类型说明submit() void提交当前值cancel() void取消编辑edit() void进入编辑模式示例script setup import { ref } from vue const editableRef ref() function forceEdit() { editableRef.value?.edit() } /script template EditableRoot refeditableRef !-- ... -- /EditableRoot /template源码中defineExpose显式暴露了这三个方法EditableRoot.vue。五、子部件与数据属性5.1 AreadivEditableArea包裹 Preview 与 Input根据状态自动附加数据属性见 EditableArea.vue可用 CSS 选择器驱动样式属性取值[data-readonly]只读时存在[data-disabled]禁用时存在[data-placeholder-shown]显示预览占位时存在[data-empty]输入为空时存在[data-focus]编辑字段聚焦时存在将被废弃改用[data-focused][data-focused]编辑字段聚焦时存在示例样式[data-reka-editable][data-focused] { outline: 2px solid var(--accent); }5.2 InputinputEditableInput附加如下数据属性见 EditableInput.vue属性取值[data-readonly]只读时存在[data-disabled]禁用时存在其余部件Preview、EditTrigger、SubmitTrigger、CancelTrigger仅提供as/asChild两个 props无额外数据属性。六、模式与行为控制6.1 激活模式 activationMode控制何时进入编辑模式支持三种取值focus默认EditablePreview获得焦点focusin即进入编辑dblclick双击预览进入编辑none不通过预览进入只能依赖EditableEditTrigger或edit()方法。对应实现位于 EditablePreview.vuehandleFocus在activationMode focus时调用context.edit()handleDoubleClick在activationMode dblclick时调用context.edit()。6.2 提交模式 submitMode控制何时提交值支持四种取值blur默认失焦即提交enter按 Enter 提交both失焦或按 Enter 都提交none仅通过EditableSubmitTrigger/submit()手动提交。实现细节EditableInput的按键处理会额外校验!event.shiftKey !event.metaKey !event.isComposing避免在组合输入如中文拼音过程中误提交EditableInput.vue而EditableRoot通过usePointerDownOutside与useFocusOutside来自/DismissableLayer监听点击外部/焦点移出按blur/both提交、否则取消EditableRoot.vue。6.3 受控与非受控非受控只传defaultValue内部通过useVModel维护状态受控传入modelValue并监听update:modelValue即标准v-model。EditableRoot v-modelname defaultValue初始值 /6.4 占位符与文本方向placeholder支持字符串或{ edit, preview }对象实现编辑态与预览态不同文案——源码中placeholdercomputed 会将字符串归一化为{ edit, preview }双份EditableRoot.vueInput 取editPreview 取previewEditableInput.vue、EditablePreview.vuedir支持 LTR/RTL通过useDirection读取缺省时继承全局ConfigProvider。七、实战示例仅点击提交按钮时提交默认行为是失焦blur即提交。若希望只有用户点击EditableSubmitTrigger时才提交例如防止误失焦丢失内容将submit-mode改为none这是官方文档的示例template EditableRoot submit-modenone EditableArea EditablePreview / EditableInput / /EditableArea EditableEditTrigger / EditableSubmitTrigger / EditableCancelTrigger / /EditableRoot /template八、源码级原理状态机与焦点管理8.1 三态切换EditableRoot内部以isEditingRefboolean为核心驱动围绕它实现三个动作函数EditableRoot.vuefunction cancel() { isEditing.value false emits(update:state, cancel) } function edit() { isEditing.value true inputValue.value modelValue.value emits(update:state, edit) } function submit() { modelValue.value inputValue.value isEditing.value false emits(update:state, submit) emits(submit, inputValue.value) }关键设计编辑期间输入内容保存在独立的inputValue中只有调用submit才写回modelValuecancel直接丢弃inputValue因此提交/取消语义严格分离。watch(modelValue)会在外部值变化时同步回inputValue保证受控模式下外部更新可正常回显。8.2 焦点托管挂载时若startWithEditMode为真则自动聚焦focus({ preventScroll: true })并在selectOnFocus时全选文本watch(isEditing)进入编辑态后nextTick聚焦输入框编辑态下点击外部区域由usePointerDownOutside/useFocusOutside统一拦截并按submitMode决定提交或取消。8.3 表单集成与无障碍传入name且处于真实表单上下文时EditableRoot会渲染一个VisuallyHiddenInput视觉隐藏的typetext输入框承载name/value/required使编辑内容可随表单提交EditableRoot.vueautoResize采用 CSS Grid 双图层方案Preview 与 Input 同占grid-area: 1 / 1编辑时切换可见性实现输入框随文本自动伸展测试文件 Editable.test.ts 通过了vitest-axe无障碍断言toHaveNoViolations并覆盖默认值、占位符、单击/双击进入编辑、selectOnFocus全选等场景。九、无障碍与键盘交互官方文档的 Keyboard Interactions 表格按键行为Tab焦点移动到编辑字段时若activation-mode为focus则切换进入编辑模式Enter若submit-mode为enter或both提交修改Escape焦点位于编辑字段上时取消修改补充说明源码验证EditablePreview带有tabindex0可被 Tab 聚焦从而触发focus激活模式Input 上 Enter 提交会忽略 Shift/Meta 组合键与输入法组合态Escape 始终调用cancel()取消后焦点语义交由浏览器按 DOM 顺序回退。十、总结Editable 通过 Root Area Preview Input 三个 Trigger 的细分结构把展示—编辑—提交/取消的状态流转封装为声明式 APIactivationMode决定何时编辑、submitMode决定何时提交、modelValue/defaultValue决定受控方式、selectOnFocus/autoResize/startWithEditMode提供细节打磨。配合完整的键盘导航、表单集成与update:state状态事件它非常适合表格单元格编辑、标题快速改名、个人资料就地修改等需要轻量编辑的交互场景。想深入源码可继续阅读 EditableRoot.vue、EditableInput.vue 与 Editable.test.ts。【免费下载链接】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),仅供参考