vue-vben-admin 为什么用 provide/inject 替代 props 穿透?3 个设计模式拆解
vue-vben-admin 为什么用 provide/inject 替代 props 穿透3 个设计模式拆解【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin你复制了 5 个几乎一样的表单弹窗每次加字段都要翻 5 遍代码vue-vben-admin 的答案是把表单、弹窗这类高频复用的 UI 零件拆成原子组件再用一个 API 对象 跨层通信把零件拼成业务页面。本文带你从源码层面看这套先拆、再通、后拼的组合式组件库设计。场景一零件的边界——Form、FormField、Modal 各自只管一件事表单只负责整表交互表单入口 vben-use-form.vue 不渲染任何具体输入框它只处理三件整表级的事转发 props、渲染默认操作按钮、拦截回车提交。function handleKeyDownEnter(event: KeyboardEvent) { if (!state?.value.submitOnEnter || !forward.value.formApi?.isMounted) { return; } // 如果是 textarea 不阻止默认行为否则会导致无法换行。 if (event.target instanceof HTMLTextAreaElement) { return; } event.preventDefault(); forward.value.formApi?.validateAndSubmit(); }字段组件只渲染一个输入框单个字段由 form-field.vue 负责它的边界清晰到只处理一件事把component: Input这样的配置解析成真实组件并挂上自己的错误状态。const FieldComponent computed(() { const finalComponent isString(component) ? componentMap.value[component] : component; if (!finalComponent) { // 组件未注册 console.warn(Component ${component} is not registered); } return finalComponent ? markRaw(toRaw(finalComponent)) : finalComponent; });注意它对未注册组件只打警告不抛错——schema 是声明式配置写错组件名时页面应该能继续渲染其他字段而不是整表崩掉。弹窗组件只管壳子modal.vue 不关心内容是什么表单还是富文本它只负责打开/关闭、锁定、loading 这些壳子状态全部交给ModalApi管理。const [Modal, modalApi] useVbenModal({ async onConfirm() { modalApi.close(); }, });如果没有这层切分一个带校验、带按钮、可回车的表单至少 300 行拆开后每个文件都能独立测试form-ui 包里就有 15 个__tests__文件对着不同切片验证。场景二状态怎么流转——API 对象 provide/inject每个组件配一个API 对象当状态中枢这是整个组件库最核心的设计useVbenForm和useVbenModal都不直接返回 DOM而是返回[组件, api]二元组。api 内部是一个响应式 storesetState、close、validate都收口在它身上。export function useVbenForm(options: VbenFormPropsany, any, any, any) { const api new FormApiany, any, any, any(options); const extendedApi api as ExtendedFormApiany, any, any, any; extendedApi.useStore (selector: any) { return useSelector(api.store, selector); }; const Form defineComponent((props, { attrs, slots }) { api.setState({ ...props, ...attrs }); return () h(VbenUseForm, { ...props, ...attrs, formApi: extendedApi }, slots); }, { name: VbenUseForm, inheritAttrs: false }); return [Form, extendedApi] as const; }摘自 use-vben-form.ts这样业务代码里formApi.validate()、modalApi.open()和组件本身是同一个响应式数据源不存在命令式 ref 和声明式 state 不同步的经典问题。用 provide 干掉 props 穿透字段组件离表单根组件隔了好几层如果靠 props 一层层传formApi每加一层渲染都要改三处代码。项目用 provide/inject 解决vben-use-form.vue 里只有两行注入provideFormProps([forward, form]); provideComponentRefMap(componentRefMap);子层任何深度都能取回const formRenderProps injectRenderFormProps(); const formApi formRenderProps.form; if (!formApi) { throw new Error(Form api is required in FormField /); }数据流向一句话描述状态在 API 对象向上子组件调 api 方法触发能力在 context向下根组件 provide任意层级 inject。props/emit 只保留给同层组件之间的直接协作比如 Form 把keydown.enter事件抛给外层处理。想看完整实现顺着 form-render/context.ts 和 use-form-context.ts 读即可。场景三组合出真实页面——弹窗里放一张表单以编辑用户信息为例页面只需要做两件事Modal 打开时回填表单、提交成功后关闭弹窗。两个组件互不知道对方的存在script setup langts import { useVbenForm, useVbenModal } from vben/common-ui; const [Modal, modalApi] useVbenModal({ async onOpenChange(isOpen: boolean) { if (isOpen) { const data modalApi.getData(); await formApi.setValues(data); // 打开即回填 } }, }); const [Form, formApi] useVbenForm({ schema: userSchema }); // 内部逻辑已封装此处省略 /script template Modal Form submittedmodalApi.close() / /Modal /template这个组合模式在 form-modal-demo.vue 里有完整可运行版本。组合优于修改源码落下来就是三条组件之间不直接引用只通过各自的 api 和 context 协作替换任何一半都不影响另一半业务差异回填、校验规则、提交接口写在页面这一层源码层永远保持不知道业务新需求优先查 schema 配置和插槽动源码前先看__tests__里有没有对应的兼容约束。避坑与进阶源码里写明的三个陷阱症状schema 里组件名拼错页面不报错原因form-field.vue 对未注册组件只console.warn不抛错设计如此。正确做法在 config.ts 的COMPONENT_MAP里确认组件名或自定义组件时通过componentMapprop 补注册别指望运行时帮你兜底。症状Modal 的 title 改了没生效原因当你用connectedComponent把 Modal 抽成独立文件后壳子上的 props 会被 use-modal.ts 显式警告拦截——When connectedComponent exists, do not set props。正确做法改状态一律走modalApi.setState({ title })而不是往Modal标签上挂属性。进阶利用内置防抖写即改即存表单值监听已经内置了防抖提交无需自己套 lodashconst handleValuesChangeDebounced useDebounceFn(async () { state?.value.submitOnChange forward.value.formApi?.validateAndSubmit(); }, state?.value?.changeDebouncedTime ?? 300);vben-use-form.vue 第 75~77 行打开submitOnChange即可获得改完 300ms 自动校验提交的行为changeDebouncedTime可配置——实时搜索类场景直接复用别重复造防抖。接着往哪走下一步你可以自己走读三个地方把这条线串起来表单原子层的 packages/core/ui-kit/form-ui/、弹窗组合层的 packages/core/ui-kit/popup-ui/以及能跑起来的组合示例 playground/src/views/examples/modal/。读完 demo 再回看__tests__里的 form-integration 测试你会更清楚这套拆—通—拼的设计在哪些边界上被反复验证过。【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

react-admin 软删除实战:深入掌握 `<DeletedRecordsList>` 组件

react-admin 软删除实战:深入掌握 `<DeletedRecordsList>` 组件

react-admin 软删除实战&#xff1a;深入掌握 <DeletedRecordsList> 组件 【免费下载链接】react-admin A frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design 项目地址: https://gitcode.co…

2026/11/12 21:19:39 阅读更多 →
Sandboxie 开源项目贡献指南:从证书体系、代码提交到沙盒问题排查的完整协作工作流

Sandboxie 开源项目贡献指南:从证书体系、代码提交到沙盒问题排查的完整协作工作流

Sandboxie 开源项目贡献指南&#xff1a;从证书体系、代码提交到沙盒问题排查的完整协作工作流 【免费下载链接】Sandboxie Sandboxie Plus & Classic 项目地址: https://gitcode.com/gh_mirrors/sa/Sandboxie Sandboxie Plus / Classic 是一款面向 Windows NT 系列…

2026/11/12 21:19:39 阅读更多 →
QQ空间备份教程:5 分钟扫一次码,历史说说 Excel+网页全量导出

QQ空间备份教程:5 分钟扫一次码,历史说说 Excel+网页全量导出

QQ空间备份教程&#xff1a;5 分钟扫一次码&#xff0c;历史说说 Excel网页全量导出 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 翻回 2014 年的说说&#xff0c;网页版要点几千次&q…

2026/10/17 10:33:17 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/11/12 5:00:00 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/11/12 5:13:20 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/12 5:13:20 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/11/12 18:22:26 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/11/12 18:22:25 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/11/12 5:13:20 阅读更多 →

日新闻

周新闻

月新闻