06-高级模式与实战项目——07. Factory模式 - 动态组件创建
07. Factory模式 - 动态组件创建概述Factory 模式是一种根据条件动态创建和返回不同组件的设计模式。它允许在运行时根据配置、类型或状态决定渲染哪个组件提高代码的灵活性和可维护性。维度内容What根据条件动态创建和返回不同组件的模式Why根据配置或状态动态渲染不同组件When根据类型渲染不同 UI、动态表单Where组件工厂函数、动态渲染Who需要条件渲染的开发者Howconst Component componentMap[type]1. 什么是 Factory 模式1.1 基本概念Factory 模式使用一个工厂函数或对象映射来动态决定创建哪个组件。// 基础工厂模式 function getComponent(type) { const components { text: TextComponent, image: ImageComponent, video: VideoComponent, }; const Component components[type] || DefaultComponent; return Component /; } // 使用 function DynamicContent({ type }) { return getComponent(type); }1.2 为什么需要 Factory 模式// ❌ 传统方式大量的条件判断 function Message({ type, data }) { if (type success) { return SuccessMessage data{data} /; } else if (type error) { return ErrorMessage data{data} /; } else if (type warning) { return WarningMessage data{data} /; } else if (type info) { return InfoMessage data{data} /; } else { return DefaultMessage data{data} /; } } // ✅ Factory 模式使用映射 const messageComponents { success: SuccessMessage, error: ErrorMessage, warning: WarningMessage, info: InfoMessage, }; function Message({ type, data }) { const Component messageComponents[type] || DefaultMessage; return Component data{data} /; }2. 基础实现2.1 组件映射// 定义组件映射 const cardComponents { user: UserCard, product: ProductCard, post: PostCard, comment: CommentCard, }; // 工厂组件 function Card({ type, data }) { const Component cardComponents[type]; if (!Component) { return div未知的卡片类型: {type}/div; } return Component data{data} /; } // 使用 function Dashboard() { const items [ { type: user, data: { name: 张三, email: zhangexample.com } }, { type: product, data: { name: 手机, price: 5999 } }, { type: post, data: { title: React 19, content: ... } }, ]; return ( div {items.map((item, index) ( Card key{index} type{item.type} data{item.data} / ))} /div ); }2.2 带默认组件const buttonVariants { primary: PrimaryButton, secondary: SecondaryButton, danger: DangerButton, success: SuccessButton, }; function Button({ variant, children, ...props }) { const Component buttonVariants[variant] || DefaultButton; return Component {...props}{children}/Component; } // 使用 Button variantprimary主要按钮/Button Button variantdanger危险按钮/Button Button variantcustom默认按钮/Button3. 高级实现3.1 动态组件注册// 组件注册表 class ComponentRegistry { constructor() { this.components new Map(); } register(name, component) { this.components.set(name, component); } get(name) { return this.components.get(name); } has(name) { return this.components.has(name); } } const registry new ComponentRegistry(); // 注册组件 registry.register(text, TextWidget); registry.register(image, ImageWidget); registry.register(chart, ChartWidget); // 工厂组件 function Widget({ type, props }) { const Component registry.get(type); if (!Component) { return div未知组件类型: {type}/div; } return Component {...props} /; }3.2 懒加载工厂// 懒加载组件映射 const lazyComponents { dashboard: () import(./Dashboard), profile: () import(./Profile), settings: () import(./Settings), }; function LazyPage({ name }) { const [Component, setComponent] useState(null); useEffect(() { const loader lazyComponents[name]; if (loader) { loader().then(module setComponent(() module.default)); } }, [name]); if (!Component) return div加载中.../div; return Component /; } // 或使用 React.lazy const pageComponents { dashboard: lazy(() import(./Dashboard)), profile: lazy(() import(./Profile)), settings: lazy(() import(./Settings)), }; function Page({ name }) { const Component pageComponents[name]; if (!Component) return div页面不存在/div; return ( Suspense fallback{div加载中.../div} Component / /Suspense ); }3.3 带参数的工厂// 工厂函数返回带配置的组件 function createField(type, config {}) { const fieldComponents { text: (props) Input typetext {...config} {...props} /, email: (props) Input typeemail {...config} {...props} /, select: (props) Select options{config.options} {...props} /, checkbox: (props) Checkbox {...config} {...props} /, date: (props) DatePicker {...config} {...props} /, }; return fieldComponents[type] || fieldComponents.text; } // 使用 function DynamicForm({ fields }) { return ( form {fields.map(field { const FieldComponent createField(field.type, field.config); return FieldComponent key{field.name} name{field.name} /; })} /form ); } // 配置 const formConfig [ { name: username, type: text, config: { placeholder: 用户名 } }, { name: email, type: email, config: { placeholder: 邮箱 } }, { name: role, type: select, config: { options: [admin, user] } }, ];4. 实际应用场景4.1 动态表单// 字段类型映射 const fieldTypes { text: ({ label, value, onChange }) ( div label{label}/label input typetext value{value} onChange{onChange} / /div ), number: ({ label, value, onChange }) ( div label{label}/label input typenumber value{value} onChange{onChange} / /div ), select: ({ label, value, onChange, options }) ( div label{label}/label select value{value} onChange{onChange} {options.map(opt ( option key{opt.value} value{opt.value}{opt.label}/option ))} /select /div ), checkbox: ({ label, checked, onChange }) ( div label input typecheckbox checked{checked} onChange{onChange} / {label} /label /div ), textarea: ({ label, value, onChange }) ( div label{label}/label textarea value{value} onChange{onChange} rows{4} / /div ), }; function DynamicField({ field, value, onChange }) { const FieldComponent fieldTypes[field.type]; if (!FieldComponent) { return div未知字段类型: {field.type}/div; } return ( FieldComponent label{field.label} value{value} checked{value} onChange{(e) onChange(field.name, e.target.value)} options{field.options} / ); } function DynamicForm({ schema, onSubmit }) { const [formData, setFormData] useState({}); const handleChange (name, value) { setFormData(prev ({ ...prev, [name]: value })); }; const handleSubmit (e) { e.preventDefault(); onSubmit(formData); }; return ( form onSubmit{handleSubmit} {schema.fields.map(field ( DynamicField key{field.name} field{field} value{formData[field.name]} onChange{handleChange} / ))} button typesubmit提交/button /form ); } // 使用 const formSchema { fields: [ { name: name, type: text, label: 姓名 }, { name: age, type: number, label: 年龄 }, { name: gender, type: select, label: 性别, options: [ { value: male, label: 男 }, { value: female, label: 女 }, ]}, { name: agree, type: checkbox, label: 同意条款 }, { name: bio, type: textarea, label: 个人简介 }, ], }; DynamicForm schema{formSchema} onSubmit{(data) console.log(data)} /4.2 动态图表const chartComponents { line: LineChart, bar: BarChart, pie: PieChart, scatter: ScatterChart, area: AreaChart, }; function Chart({ type, data, options }) { const ChartComponent chartComponents[type]; if (!ChartComponent) { return div不支持的图表类型: {type}/div; } return ChartComponent data{data} options{options} /; } // 使用 const charts [ { type: line, data: lineData }, { type: bar, data: barData }, { type: pie, data: pieData }, ]; function Dashboard() { return ( div classNamedashboard {charts.map((chart, i) ( Chart key{i} type{chart.type} data{chart.data} / ))} /div ); }4.3 动态通知const notificationComponents { success: ({ message, onClose }) ( div classNamenotification success span✅ {message}/span button onClick{onClose}×/button /div ), error: ({ message, onClose }) ( div classNamenotification error span❌ {message}/span button onClick{onClose}×/button /div ), warning: ({ message, onClose }) ( div classNamenotification warning span⚠️ {message}/span button onClick{onClose}×/button /div ), info: ({ message, onClose }) ( div classNamenotification info spanℹ️ {message}/span button onClick{onClose}×/button /div ), }; function Notification({ type, message, onClose }) { const Component notificationComponents[type] || notificationComponents.info; return Component message{message} onClose{onClose} /; }5. 完整示例CMS 页面构建器// 组件库 const componentLibrary { hero: ({ title, subtitle, image }) ( div classNamehero img src{image} alt{title} / h1{title}/h1 p{subtitle}/p /div ), features: ({ items }) ( div classNamefeatures {items.map((item, i) ( div key{i} classNamefeature h3{item.title}/h3 p{item.description}/p /div ))} /div ), testimonial: ({ quote, author, role }) ( div classNametestimonial p{quote}/p div classNameauthor strong{author}/strong span{role}/span /div /div ), pricing: ({ plans }) ( div classNamepricing {plans.map(plan ( div key{plan.name} classNameplan h3{plan.name}/h3 div classNameprice¥{plan.price}/div ul {plan.features.map(feature ( li key{feature}{feature}/li ))} /ul /div ))} /div ), cta: ({ title, buttonText, buttonLink }) ( div classNamecta h2{title}/h2 a href{buttonLink} classNamebutton{buttonText}/a /div ), }; // 页面组件 function PageBuilder({ sections }) { return ( div classNamepage-builder {sections.map((section, index) { const Component componentLibrary[section.type]; if (!Component) { return div key{index}未知组件类型: {section.type}/div; } return Component key{index} {...section.props} /; })} /div ); } // 页面配置 const pageConfig { sections: [ { type: hero, props: { title: 欢迎来到我们的网站, subtitle: 最好的产品和服务, image: /hero.jpg, }, }, { type: features, props: { items: [ { title: 功能1, description: 描述1 }, { title: 功能2, description: 描述2 }, { title: 功能3, description: 描述3 }, ], }, }, { type: testimonial, props: { quote: 非常棒的产品, author: 张三, role: CEO, }, }, { type: pricing, props: { plans: [ { name: 基础版, price: 99, features: [功能1, 功能2] }, { name: 专业版, price: 199, features: [功能1, 功能2, 功能3] }, ], }, }, { type: cta, props: { title: 开始使用, buttonText: 立即购买, buttonLink: /pricing, }, }, ], }; // 使用 function HomePage() { return PageBuilder sections{pageConfig.sections} /; }6. 总结核心要点要点说明核心价值动态选择组件避免条件判断实现方式对象映射、工厂函数、注册表适用场景动态表单、CMS、多类型组件优势可扩展、易维护记忆口诀工厂模式动态选映射对象最方便类型配置决定 UI扩展新类不用愁7. 相关资源工厂模式React 动态组件

相关新闻

《重启日记》第十五周|工具提效挤占写作时间,少更也守住长期节奏

《重启日记》第十五周|工具提效挤占写作时间,少更也守住长期节奏

一、本周数据全景总览(06.29-07.06)周次阅读量原力值周排名第十四周141211961054第十五周42712062868十五周成绩单:总访问量稳步累加,原创文章累计 139 篇,连续更新 15 周。原力值从 1196 上涨至 1206,连续…

2026/7/7 1:57:51阅读更多 →
《HarmonyOS技术精讲-Core File Kit》第15篇:错误处理与异常排查指南

《HarmonyOS技术精讲-Core File Kit》第15篇:错误处理与异常排查指南

《HarmonyOS技术精讲-Core File Kit》第15篇:错误处理与异常排查指南 文件操作是应用开发中最基础也最容易出问题的环节。HarmonyOS NEXT 的 Core File Kit 提供了统一文件访问接口,但很多开发者遇到文件操作异常时,只做了简单的 try-catch&…

2026/7/7 1:57:51阅读更多 →
Rust-GUI图形库:Iced 计数器项目完整搭建教程(1)

Rust-GUI图形库:Iced 计数器项目完整搭建教程(1)

一、前置环境准备 官网下载安装:https://www.rust-lang.org/tools/install rustc 1.96.1 (31fca3adb 2026-06-26) 二、创建项目 Windows 打开 PowerShell / Linux/macOS 终端执行 1. 创建二进制项目 # 创建名为 iced_counter 的项目 cargo new iced_co…

2026/7/7 1:57:51阅读更多 →
ps怎样制作拼图效果?ps制作拼图效果的步骤

ps怎样制作拼图效果?ps制作拼图效果的步骤

本文详细讲解两种图片拼图效果制作方式,包含传统 PS 手动定义图案制作拼图完整实操步骤,以及使用StartAI插件Banana修图功能生成规整立体拼图特效的快捷方法,对比 PS 手工操作与 StartAI AI Banana修图的效率差异,零基础美工也能快…

2026/7/7 3:12:58阅读更多 →
COCO与YOLO格式转换指南:目标检测数据标准化

COCO与YOLO格式转换指南:目标检测数据标准化

1. 目标检测数据格式概述在计算机视觉领域,目标检测任务需要统一的数据格式来存储标注信息。目前主流的数据格式主要有两种:COCO格式和YOLO格式。这两种格式各有特点,适用于不同的场景和框架。COCO(Common Objects in Context&…

2026/7/7 3:12:58阅读更多 →
Stable Diffusion本地部署全攻略:从环境配置到高级应用

Stable Diffusion本地部署全攻略:从环境配置到高级应用

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 1. 为什么选择本地部署Stable Diffusion? 最近在AI绘画领域,相信很多开发者都遇到了一个共同的痛点&#xff…

2026/7/7 3:12:58阅读更多 →
mysql数据库的连接

mysql数据库的连接

方式一:开始栏中搜索mysql找到图中所示点击后输入密码即可方式二:开始栏中搜索cmd右键管理员身份运行输入:mysql -uroot -p 接下来输入数据库密码即可

2026/7/7 3:12:58阅读更多 →
旅行Agent开发者的机会:中国AI酒店预订爆发式增长

旅行Agent开发者的机会:中国AI酒店预订爆发式增长

核心结论:AI Agent正在从"旅行灵感工具"快速进化为"搜索-比价-决策-预订"的全链路入口——近九成旅客愿意用AI找酒店,66%实际使用AI预订酒店,价格监控和动态比价是当前渗透率最高的Agent应用场景。一、搜索酒店&#xff…

2026/7/7 3:12:58阅读更多 →
2026年点胶机该选谁?不同需求场景适配选型指南

2026年点胶机该选谁?不同需求场景适配选型指南

点胶机选型核心需求梳理方法点胶设备采购的适配性直接影响生产良率、产能效率与投入回报比,选型前完成系统的需求梳理,可避免盲目追求高参数或压低预算导致的设备错配,降低后续试错成本。核心需求梳理维度说明需求梳理可从5个核心维度展开&am…

2026/7/7 3:07:57阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/6 4:26:20阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/7 2:56:31阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/7 1:03:28阅读更多 →
Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

Acunetix v24.8 深度解析:DAST漏洞扫描器核心原理与DevSecOps实践

1. 项目概述:Acunetix v24.8 高级版漏洞扫描器深度解析作为一名在网络安全领域摸爬滚打多年的老兵,我深知一款趁手的“兵器”对于安全测试工作意味着什么。今天要聊的,就是Web应用安全测试领域里一个响当当的名字——Acunetix。特别是其v24.8…

2026/7/7 0:02:41阅读更多 →
国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot)

国产化信创改造:达梦/人大金仓适配与多数据库兼容方案实战(SpringBoot) 🌐 演示地址:http://ruoyioffice.com | 📦 源码1GitHub:ruoyi-office | 📦 源码2GitCode:ruoyi-o…

2026/7/7 0:02:41阅读更多 →
CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS 7/8 SSH 连接失败:5步系统性排错流程与决策树

CentOS SSH连接故障排查:从基础检查到深度修复的完整指南引言当你尝试通过Xshell或其他SSH客户端连接CentOS服务器时,突然遭遇"Connection refused"或"Connection timed out"的错误提示,这种经历对任何运维人员或开发者来…

2026/7/7 0:02:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/6 4:45:01阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/6 4:45:01阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/6 4:45:03阅读更多 →