大概一个月前,我接到一个需求:给某公司的官网做一套Demo,需求方原话就是“实现官网demo(8+1)”。当时我第一反应是这活儿挺简单,8个页面加1个页面而已,撑死一周搞定。结果做到一半就发现,真正花时间的不是写页面,而是把“8+1”这个数字背后隐含的需求拆清楚。因为“8+1”到底指哪8个页面、那1个特殊页面是什么形态,需求方自己往往也只有一个模糊的概念。
这篇文章就把我做这类官网Demo的完整过程写下来,包含需求拆解、设计还原、组件复用、特殊页面实现、响应式与性能优化、以及最后的演示交接。内容不局限于某个具体框架,思路和步骤可以直接复用到React、Vue或者原生开发场景里。无论你是刚接外包的新手,还是需要快速交付演示版本的老手,都应该能从中找到一些能直接落地的经验。
1. 先搞清楚“8+1”到底指什么:需求拆解比写代码重要
很多人拿到“官网demo(8+1)”这种描述后,第一件事就是打开代码编辑器开始搭首页。我劝你先别急着写代码。一个模糊的“8+1”如果不拆明白,后面八成会返工。比如你做了一版“8个页面”是按照企业官网常见的结构做的,结果需求方心里的“1”是某个业务功能页,或者是嵌套在某个栏目下的一二级页面组合,那整套页面结构都得调整。
1.1 第一件事:把每一页的职责写下来
我见过太多人直接打开设计稿或者直接凭感觉列出页面清单,然后就开始做。正确做法是先和需求方过一遍“页面职责”。什么叫页面职责?就是每一个页面具体承载什么信息、回答用户的什么问题。拿最常见的官网结构来说,8个常规页面多半是这样:
| 页面 | 核心职责 | 主要模块 |
|---|---|---|
| 首页 | 介绍公司是谁、业务是什么、核心卖点 | Hero首屏、核心业务、数据指标、客户案例、CTA |
| 关于我们 | 建立信任感 | 公司介绍、发展里程碑、团队亮点、资质荣誉 |
| 产品与服务 | 展示提供什么 | 产品/服务卡片、解决方案场景、价格或流程 |
| 产品详情 | 深挖某一项产品 | 功能列表、技术参数、适用场景、FAQ |
| 案例展示 | 用事实说服 | 案例列表、行业分类筛选、精选项目 |
| 新闻动态 | 展示企业活力和专业性 | 文章列表、热门标签、订阅入口 |
| 联系我们 | 降低沟通门槛 | 表单、联系方式、地图、工作时间 |
| 团队介绍 | 拉近用户距离 | 核心成员卡片、岗位职责、文化价值观 |
这个表列出来之后,你一定要拿给需求方确认。说10分钟,但能省下后面几天返工的时间。尤其是产品详情和案例展示两个页面,如果导航里把它们作为二级路由藏在产品/案例下面,那“8个页面”可能是“8个一级路由”;如果导航直接平铺,又是另一种结构。这个不确认清楚,后面所有的路由和组织关系都是空中楼阁。
1.2 “+1”那一个页面才是真正的验收重点
“8+1”里的“1”通常是整个项目的点睛之笔。我接过的几版类似需求中,这个“+1”出现过这些形态:
- 一个具备筛选和搜索功能的案例列表页,因为普通案例页是静态的,带筛选的交互页更接近真实产品;
- 一个包含表单校验的在线预约/咨询页,用于演示销售线索收集闭环;
- 一个简易的后台数据看板页,用于向投资人展示项目可扩展性;
- 一个常见问题(FAQ)页,带手风琴交互和搜索定位。
这个“1”往往不是设计稿里就有的,而是需求方觉得“官网不能只是展示,还得有点别的”。所以我的策略是:在开工之前主动给需求方二选一的方案建议。不要问他“你想要什么”,而是要拿出两个专业方向让他选。比如“加一个带筛选的案例列表页还是加一个表单预约页”,这两个方向都符合官网Demo的演示逻辑,但实现成本和视觉冲击力完全不同。需求方一旦选了,后面的工作方向就非常明确了。
2. 开工前的设计还原与素材整理:三个前置准备不能省
页面清单确认之后,第二个容易翻车的地方是素材整理。很多人以为拿到了设计稿就能直接开工,实际情况往往是设计师发你一个几十MB的PSD或者Sketch包,里面图层乱七八糟,切图缺失,字体没有导出,图标全是位图。你得花不少额外时间清理。与其到时候手忙脚乱,不如开工前先花半天把素材整理规范。
2.1 把设计稿拆成“组件清单”而不是“页面截图”
拿到设计稿后,我习惯先把所有页面的公共部分圈出来。导航栏、页脚、面包屑、按钮、卡片、表单这些大概率在多个页面中重复出现,它们才是真正的开发核心。我会建一个表格,把每个公共组件对应到具体页面位置,再标注它的状态变化。
比如一个按钮组件,至少要有默认态、悬浮态、点击态和禁用态。很多设计稿只画了默认态,那么我在开发时会按照主色调整悬浮和点击态,把禁用态也做了。这些状态在做Demo演示时未必用得上,但一旦需求方说“这个按钮点了能不能换个颜色”,你就不会手忙脚乱。
图标的处理也需要注意。现在很多设计稿里的图标是图片格式,放到页面上会有锯齿或者尺寸不匹配。我一般会优先在图标库里用同名图标替换,确保所有图标都是SVG格式。
2.2 用CSS变量把视觉规范变成代码
设计稿里的色板、字号、间距如果直接硬编码,后面调整样式时会非常痛苦。我的习惯是在项目入口文件里定义一套CSS变量,把主色、辅助色、文字色、圆角半径、阴影、间距倍数全部抽出来。这样后续统一改主题色的时候,只需要改两三个变量就够了。
:root { --color-primary: #2563eb; --color-primary-hover: #1d4ed8; --color-text-main: #1f2937; --color-text-secondary: #6b7280; --color-bg-light: #f8fafc; --radius-md: 8px; --shadow-card: 0 2px 12px rgba(0, 0, 0, 0.06); --space-1: 4px; --space-2: 8px; --space-3: 16px; --space-4: 24px; --space-5: 32px; }这套变量建立之后,页面上所有的间距尽量按space的倍数走,不该出现随手的margin值。设计还原度的高低,很多时候就差在这些细节里。还有一个容易被忽略的地方:字体。做官网Demo的时候,字体不像色板那么显眼,但一旦用错,整个页面的专业感就没了。我通常直接用系统字体栈配置,避免因为系统差异导致预览效果不一致。
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; }2.3 目录结构按功能拆,而不是按页面拆
官方Demo的代码结构,我见过很多人按页面目录堆文件:pages/home、pages/about、pages/product。前期这么做很顺手,但页面一多,公共代码和各页面特有的逻辑就混在一起了。正确的做法是按下层目录来分:components放公共组件,views放页面级组件,layout放整体布局,assets放静态资源,utils放工具函数,api放接口请求封装。这样做的好处是,那8个页面虽然互相独立,但公共逻辑可以被集中管理。
3. 页面骨架与公共组件:8个页面的复用策略
页面清单和素材整理好之后,才轮到真正的页面开发。这个阶段我最想分享的一个经验是:不要一个页面一个页面从头写,先把整个站点的骨架和公共组件搭好,然后像拼积木一样去拼页面。这样做的好处是效率极高,而且页面之间的风格统一性远超你想象。
3.1 用“布局+模块”的思想替代“复制粘贴”
官网类项目有一个特点:很多页面之间只有中间内容区域不同,页头页脚完全一样。所以我会先把Layout搭出来,把Header、Footer、Breadcrumb这些公共部分放进去,中间用路由出口承接页面内容。
// 以 React 路由为例的简化版 Layout import { Outlet } from "react-router-dom"; import SiteHeader from "@/components/layout/SiteHeader"; import SiteFooter from "@/components/layout/SiteFooter"; export default function MainLayout() { return ( <div className="site-layout"> <SiteHeader /> <main className="site-main"> <Outlet /> </main> <SiteFooter /> </div> ); }这样所有页面自动获得统一的页头页脚,换一次导航就能全局生效,不会出现某个页面改了导航另一个没改的尴尬。页面内容部分,我也不会按照整页的逻辑去写。我会把页面的每一块内容拆成组件,比如首页就可以拆成Hero、业务优势、数据展示、案例引用、CTA区域。这些组件做成独立的,之后在别的页面里也能复用。
3.2 从首页到内页:优先做“最重的页面”
很多人的工作习惯是按导航顺序从左到右做页面,先做首页,再做关于我们。我的习惯是先做“最重”的那个页面,也就是内容最丰富、模块最多的页面。官网Demo里通常是首页,也可能是产品列表页。
为什么先做重页面?因为重页面会覆盖最多的组件类型,把首页做完,公共组件差不多用完了一遍。后面的内页大概率只是换内容排列。而且先做重页面还有一个好处:尽早发现公共组件的边界。如果你发现首页里有个区域在其他页面里也用得到,就顺手把它抽成公共组件,不用等到做内页的时候再回头改。
3.3 卡片类组件让页面既统一又灵活
官网Demo里,产品介绍、团队介绍、新闻列表、案例展示这些页面,核心都是卡片。把卡片组件抽象好,做页面就和填表一样简单。我会对卡片组件做一层统一封装,让主要属性通过参数传入。
// ProductCard 的简化示意 export default function ProductCard({ icon, title, description, tags, action }) { return ( <div className="product-card"> <div className="product-card__icon">{icon}</div> <h3 className="product-card__title">{title}</h3> <p className="product-card__desc">{description}</p> {tags?.length ? ( <div className="product-card__tags"> {tags.map((tag) => ( <span key={tag} className="tag">{tag}</span> ))} </div> ) : null} {action ? <div className="product-card__action">{action}</div> : null} </div> ); }通过传参控制显示状态,卡片在新闻列表、案例展示、产品介绍里都能用。如果某个页面的卡片形态和默认的差异较大,可以通过扩展参数的方式增加新样式,而不是新开一个组件。
3.4 内页用“容器+区块”快速批量完成
对于关于我们、新闻动态这类以文章内容为主的内页,我不需要设计很复杂的结构。一个内容容器,加一个侧边栏,基本就能撑起来。批量做内页时,我会预先定义好内容区块的样式类,比如页面标题栏、内容卡片、列表分隔线,然后按页填充。
这个阶段的关键是保持克制。官网Demo不需要每个页面都长得不一样,反而应该尽量保持一致,让用户看到第四五个页面时形成对网站整体风格的认知。如果你在每一页都加新样式,最后演示时看起来就像五个不同的网站在切换,需求方会不满意的。
4. 第“+1”个页面:不能套模板的重头戏
前面8个页面做完整体结构就成型了,但整个Demo能不能让需求方眼前一亮,往往取决于“+1”那个页面。这个页面必须比普通内页多一层交互逻辑,才有存在的意义。
4.1 为什么“+1”页不能直接套普通列表页模板
假设需求方选的是“带筛选的案例展示页”,如果你只是把普通案例页的静态卡片换成几个筛选按钮,那演示效果等于零。真正的筛选页需要满足几个条件,才能让看Demo的人感觉“这网站是活的”。
- 筛选项能真实过滤数据,而不是只做表面切换;
- 列表区域要有加载状态,点击筛选后能感知到数据刷新;
- 结果为空时要有友好的空状态提示;
- 最好支持URL参数同步,刷新页面后筛选条件不丢失。
这几个条件看似简单,实际上已经涉及前后端联动的思路。做Demo的时候,我们不需要真的部署后端,用Mock数据模拟即可。但交互路径必须完整。
4.2 一个“预约表单页”的完整实现逻辑
如果第“+1”个页面是预约表单,我会重点打磨三个点:表单校验、提交状态、成功反馈。
表单校验里最容易被忽略的是“模糊提示”和“边界情况”。比如手机号校验,不能只判断是不是11位数字,还要考虑用户可能输入空格、横线,或者用座机号码。合理的做法是输入时去掉空格和横线后再校验,校验不过就给出具体提示。密码这类的信息虽然官网联系不大,但如果需要邮箱或者手机号,就要同步追踪。
// 手机号校验的简化示意 function normalizePhone(value) { return value.replace(/[\s-]/g, ""); } function isValidPhone(value) { return /^1[3-9]\d{9}$/.test(normalizePhone(value)); }提交状态也要做的像真实应用。用户点击提交按钮之后,按钮要进入loading状态,防止重复提交;提交完成后跳转到一个成功页或者弹窗;如果提交失败,要保留用户填写的内容,而不是把表单清空。很多Demo开发者的做法是:点击提交,直接弹一个“提交成功”的alert。需求方可能觉得太假了。一个合格的Demo应该是:点击提交,按钮转圈一秒左右,然后出现成功提示,并把表单置为已提交状态。这个体验上的细节,反而是需求方最容易感知到“专业”的地方。
4.3 空状态、加载态与错误处理:Demo也要有状态设计
我见过最多的Demo问题就是:页面永远展示满屏数据,而且所有资源秒开。这看起来很好,实际上反而显得假。真实网站有网络延迟,有加载过程,有用户搜索不到内容的场景。一个高质量的“+1”页面,一定要把三种状态做全。
加载态就是骨架屏或者旋转图标,空状态是“没有找到相关内容”的提示卡片,错误状态是接口异常时展示的可重试界面。这三种状态在演示时未必会触发,但如果你做了,演示时可以主动演示给需求方看:“你看,这个是空状态,这个是加载状态。”这个动作会让需求方觉得你很懂产品,而不只是在完成页面还原。
5. 响应式适配与性能优化:官网Demo最容易翻车的两个点
官网类项目的特殊之处在于,它一定会被人在电脑上打开看,也可能被拿着手机看。需求方如果在手机上打开你的Demo,发现导航错位、图片变形,前面所有的好感都会烟消云散。所以我都会在开发阶段就把响应式和性能问题考虑进去,而不是最后一起处理。
5.1 用三段式断点覆盖真实设备
做响应式,我先定三个断点:移动端优先考虑360px到480px,平板从768px到1023px,桌面端从1024px以上。我的做法是桌面端优先设计,再收窄到平板和手机。因为官网Demo通常逻辑简单,桌面端能通过样式调整适配到手机,反之则很麻烦。
/* 断点示意 */ @media (max-width: 768px) { .site-header__nav { /* 导航转为汉堡菜单或其他折叠形态 */ } .page-section { padding-left: 16px; padding-right: 16px; } } @media (min-width: 769px) and (max-width: 1023px) { .page-section { padding-left: 32px; padding-right: 32px; } } @media (min-width: 1024px) { .page-section { max-width: 1200px; margin-left: auto; margin-right: auto; } }响应式最容易出问题的组件是导航和卡片网格。导航在桌面端是水平排开,在手机端往往需要折叠成一个汉堡菜单;卡片网格在手机端要变成单列。我的经验是:导航菜单直接用flex换行配合滚动下拉,卡片网格用grid的auto-fill自动填充列数,尽量避免纯靠media query一个个调整。
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 24px; }这套写法在手机、平板、桌面都能自动适配,比硬编码列数的人类很多。
5.2 图片与字体优化:别让首页首屏卡到没法看
官网Demo最常见的性能问题是首屏加载一堆大图。特别是首页Hero区域,如果设计师给你的是一张2MB的PNG,直接放上去会让页面加载慢得令人发指。我的处理方案是:
- 位图图片全部转成WebP格式,体积能降一半以上;
- 首屏大图使用预加载,降低视觉突兀感;
- 非首屏图片使用懒加载,滚动到视口附近才加载;
- 图标和logo优先使用SVG,没有SVG的用内联data URI替代。
// 懒加载写法示意(React 中) function LazyImage({ src, alt }) { return <img src={src} alt={alt} loading="lazy" />; }字体方面,官网Demo不建议直接引一大套自定义字体,尤其是中文字体,动辄几MB。我一般只用一两个字重的系统字体,或者引入字体库的子集版本。如果没有严格的品牌字体要求,直接使用系统字体栈反而是最优选择。
5.3 真机过一遍的排查清单
只靠DevTool模拟器检查响应式远远不够。我建议开发和演示前,至少在真机上过一遍以下排查清单:
- 首页首屏文字是否可读,图片是否变形;
- 导航栏在手机端是否可展开/收合,收合后页脚是否被遮挡;
- 点击卡片跳转是否能正常返回,返回后滚动位置是否合理;
- 表单输入框在手机上是否会唤起正确的数字键盘或邮箱键盘;
- 横向滚动是否存在,检查具体是哪个元素溢出;
- 所有弹窗和抽屉在手机尺寸下是否完整显示内容。
这里面最容易被坑的是横向滚动,经常是某个表格或者图片固定宽度超了,排查起来很费时间。我的检查方法是在浏览器里选中根节点看滚动宽度,看是哪个子节点超出。一般几十秒就能定位。
6. 演示与交接:最后一步决定项目成败
很多做Demo的人把代码写完就认为完工了,然后直接把压缩包扔给需求方。这是一个非常大的误判。官网Demo是拿来给人看的,如果对方打不开、运行不起来、或者打开后效果和你的本地开发环境天差地别,你的工作就白费了。
6.1 让需求方五分钟内就能看到效果
Demo的可用性是交付的第一前提。最简单的办法:部署到静态托管平台上,生成一个可直接访问的网址。现在常用的静态托管平台很方便,绑定代码仓库后,每次提交代码都会自动构建更新。
如果因为备案、域名或者网络原因没法快速部署,还有一个备用方案:在本机起一个Node服务,然后通过内网穿透工具生成一个临时访问链接。这个方案适合短期演示,链接可以在有效期内让任何人访问到Demo。
不管用哪种方式,你一定要把演示网址和操作说明写进交付文档。不要指望需求方会自己琢磨怎么跑代码。如果需求方懂开发,他自然会看源码;如果他不懂,一个网址比一堆命令管用得多。
6.2 演示脚本与验收清单
做好部署之后,不能直接打开网址乱点。我会准备一份演示脚本,约定演示的路径。什么是演示脚本?就是一条有逻辑的主线。比如从首页开始,先说清楚公司业务定位;然后点击导航到产品中心,展示核心业务卡片;接着切换到带筛选的案例页,演示筛选交互和数据更新;再打开一个详情页,展示信息架构;最后在预约表单页演示一次完整的表单提交流程。
演示脚本的价值在于避免现场忘词或乱点,让整个演示节奏非常紧凑。同时也可以准备一份验收自查表,把之前拆解过的页面职责和功能点全部列成勾选项,在交付之前检查一遍。这个表格还可以发给需求方自己勾选,让验收过程清晰可见。
6.3 交付物清单与后续迭代
最后整理交付物时,不要只发一个代码仓库地址就完事。一份合格的交付至少应该包含:
- 演示环境地址,让需求方能直接看效果;
- 源码仓库地址,包含完整的README说明;
- 环境变量示例文件,让接手的开发者能快速配置;
- 设计稿、切图、图标等原始素材的归档链接;
- 项目结构和页面路由的简要说明文档。
如果后续需求方想继续迭代,最好在交付文档里写清楚“当前实现的技术边界”。比如哪些地方用的是Mock数据,哪些交互是纯前端模拟,接真实接口时需要改哪些地方。这样接手的下一任开发者不用再去代码里猜来猜去。
我在实际交付中还有一个习惯:把演示录像发一份过去。哪怕是临时用录屏工具录的几分钟视频,对需求方来说也非常直观,尤其是他没法立刻打开演示链接的时候。这个细节成本很低,但效果很好。做官网Demo这件事,说到底不是考技术难度,而是考谁更能理解“演示”二字的分量。代码能力只是底线,需求拆解、素材管理、组件抽象、交互补全、响应式适配、部署交付,每一环都会影响最终评价。希望这篇“8+1”实战记录,能让你下次拿到类似需求的时候少走几条弯路。