简介:直接可用的小米商城风格前端练习项目,包含三个独立页面:首页(index.html)、搜索页(search.html)、商品详情页(product.html),每个页面配专属CSS文件(indexStyle.css、search.css、product.css)和基础交互脚本(indexJs.js + jquery-3.3.1.js)。采用语义化HTML5编写,实现响应式导航栏、轮播图占位区、商品卡片列表、搜索框组件、底部版权栏等典型电商模块。内置全部所需图片资源,如xiaomi.png、search.png、house.png、car.png、like.png、wechat.png、sina.png、icon.png等共20余张,覆盖图标、按钮、示意图形等场景;另附销售流程图(saleprocess.png)及界面参考图(picture.png、video.png)。所有代码无框架依赖,结构清晰分层,支持双击直接在浏览器中运行,适合HTML/CSS初学者动手练习页面结构拆分、样式组织与基础交互实现。
1. 项目概述:为什么从“小米商城三页”开始练手,比写个待办清单更有价值?
前端入门最常踩的坑,不是不会写 div,而是不知道“一个真实页面到底该怎么拆”。你可能背过语义化标签的定义,但真打开小米官网,看到那个悬浮导航栏、轮播图下方整齐排列的六宫格商品、搜索框右侧动态变化的热搜词——你会突然卡住:这些模块之间谁该包着谁?CSS里用 flex 还是 grid 更合理?图片资源怎么命名才不至于三天后自己都找不到 sh.png 到底是“手机”还是“售后”?这套“小米商城三页仿写实战包”,就是专治这种“理论懂、动手懵”的实操解药。它不教你抽象概念,而是把一个成熟电商产品的最小可行界面单元——首页、搜索页、商品详情页——完整切出来,给你一套能双击就跑、结构清晰、资源齐备的代码。关键词里的“小米商城”不是噱头,是锚点:它的视觉节奏克制、留白呼吸感强、色彩系统干净(深灰+橙红+白),对初学者极其友好;“HTML5仿写”意味着你必须亲手写 <header> <nav> <main> <section>,而不是靠框架生成一堆 div class="container";“CSS响应式”不是一句口号,而是你能在 indexStyle.css 里亲眼看到媒体查询如何从 1200px 断点逐步退化到 768px 再到 480px,连轮播图占位区的高度都是用 min-height: calc(100vh - 120px) 算出来的;“前端练习”四个字背后,是每个 .html 文件里都藏着的“可调试线索”——比如 search.html 中搜索框的 input 元素绑定了 oninput 事件,但实际交互逻辑被刻意留在 indexJs.js 的注释里,等你去补全;而“商品详情页”这个关键词,直指电商核心——它逼你处理图片懒加载占位、规格选择器状态切换、加入购物车按钮的禁用/启用逻辑,这些都不是 alert("Hello") 能覆盖的。我带过几十个零基础学员,凡是坚持把这三页从头手敲一遍、再逐行改样式调布局的,两周后就能独立完成公司内部管理系统首页的重构。因为这不是抄作业,是跟着一个成熟产品的骨架,一节一节地长出自己的肌肉。
2. 整体架构设计与思路拆解:为什么是三个独立HTML+三个CSS,而不是一个SPA?
很多人拿到这个包第一反应是:“啊?怎么不是 Vue 或 React?还要写三个 HTML?” 这恰恰是本项目最硬核的设计选择。我们先看目录树里那几个关键文件:index.html、search.html、product.html 是三个完全独立的 HTML 文档,各自引入专属 CSS(indexStyle.css、search.css、product.css)和共用 JS(jquery-3.3.1.js 和 indexJs.js)。这种“多页应用(MPA)”结构,绝非技术落后,而是精准匹配初学者的认知负荷曲线。想象一下,如果你刚学会用 flex-direction: column 排列导航菜单,突然要理解 Vue Router 的路由守卫、组件复用、状态管理,大脑会直接宕机。而 MPA 的优势在于边界清晰、错误隔离、调试直观。你在 index.html 里把轮播图的 overflow: hidden 写错了,只会影响首页,刷新页面就能看到效果;在 search.html 里误删了搜索框的 id="search-input",indexJs.js 里对应的 $("#search-input").on("input", ...) 就会报错,控制台一眼定位问题——这种“所见即所得”的反馈闭环,是框架封装掉底层细节后最难获得的。更关键的是,这种结构强制你思考页面职责分离:首页的核心是“信息聚合与品牌露出”,所以 indexStyle.css 里重点处理全局导航、轮播图、商品瀑布流;搜索页的核心是“意图识别与结果呈现”,search.css 就聚焦于搜索框的聚焦态、热搜词标签云、结果列表的卡片间距;商品详情页的核心是“决策促成”,product.css 则精细控制图片画廊、规格选择器的 hover 反馈、购买按钮的悬停变色。三个 CSS 文件的命名不是随意的,indexStyle.css 带 “Style” 后缀,暗示它承载了部分全局样式(如字体、链接默认色),而 search.css 和 product.css 是纯粹的页面级样式,避免污染。至于 JS 层,jquery-3.3.1.js 提供 DOM 操作基础能力(毕竟初学者写原生 querySelectorAll 容易漏掉 forEach),而 indexJs.js 是你的“实验田”——里面预埋了首页轮播图的定时器骨架、搜索页的输入防抖伪代码、详情页的规格选择逻辑注释,等着你用 jQuery 填充血肉。这种“HTML 定义结构、CSS 控制表现、JS 驱动交互”的三层分离,不是教科书理论,是你在 product.html 里删掉一行 <script src="indexJs.js">,立刻发现“加入购物车”按钮失去响应的真实体验。我试过把这套结构改成单页应用,结果学员花了三天纠结路由配置,却没搞懂一个 position: sticky 导航栏是怎么粘在顶部的。真正的工程思维,始于尊重复杂度的分层,而非盲目追求“高大上”。
3. 核心模块解析与实操要点:从一张 xiaomi.png 看懂资源组织逻辑
别小看目录里那堆 .png 图片,它们是检验你是否真正理解前端工程化的第一道关卡。打开资源包,你会发现 xiaomi.png(小米 Logo)、search.png(放大镜图标)、house.png(首页图标)、car.png(购物车图标)、like.png(收藏图标)、wechat.png(微信图标)、sina.png(微博图标)、icon.png(通用图标)、up.png(回到顶部箭头)……总共 20 多张。初学者常犯的错误是:把所有图片扔进根目录,然后在 HTML 里写 <img src="xiaomi.png">。这套实战包的做法截然不同——它用语义化命名 + 场景化归类构建了一套隐形规范。xiaomi.png 放在根目录,因为它是品牌标识,首页、搜索页、详情页的 <header> 里都会引用,属于全局资源;而 search.png、house.png、car.png 这些导航图标,虽然也高频出现,但它们的尺寸、颜色状态(正常/悬停/点击)往往需要微调,所以项目虽未显式建 icons/ 目录,但你在 search.css 里会看到 .search-icon { background: url('search.png') no-repeat center; },这种写法暗示了未来扩展性:当你需要深色模式时,只需替换 search-dark.png 并在媒体查询里切换 background-image。更值得玩味的是那些看似随意的文件名:15.png、7.png、99.png、sh.png、repair.png、DmyRyTulHhd8JBcWLqzn-master-7afd7538d985068a430e3ce4a63de056f4dcf774。它们不是乱码,而是真实开发中常见的“临时资源”痕迹。15.png 很可能是某款手机主图的第 15 张版本(设计师发来的命名),sh.png 是“售后服务(Service & Help)”缩写,repair.png 直接指向维修服务图标。那个超长字符串文件名?它极大概率是 GitHub 下载 ZIP 包时自动生成的 commit hash 命名,提醒你:生产环境的资源路径管理,永远要面对第三方库、CDN 缓存、版本回滚等现实问题。实操中,我建议你第一步不是写代码,而是打开 index.html,找到 <header> 里的 Logo 引用:<img src="xiaomi.png" alt="小米商城">,然后手动把它剪切到新建的 assets/images/ 目录下,再把 HTML 中的 src 改为 "assets/images/xiaomi.png"。接着,打开 indexStyle.css,找到轮播图占位区的背景图声明:.banner-placeholder { background: url('picture.png') ... },同样把它移到 assets/images/ 并更新路径。这个看似繁琐的过程,其实在训练你两个核心能力:一是路径意识——相对路径 ./assets/images/ 和绝对路径 /assets/images/ 在本地双击运行和部署到服务器时的行为差异;二是资源映射能力——看到 picture.png 就知道它对应 saleprocess.png 旁边的界面参考图,看到 video.png 就明白它是商品视频封面占位符。这种能力,在你日后接手一个有 500+ 张图片的遗留项目时,会救你无数次。另外,所有图片资源都经过了尺寸预处理:xiaomi.png 是 120x40px(适配导航栏高度),search.png 是 24x24px(匹配图标容器),picture.png 是 1920x600px(全屏轮播图宽高比)。这意味着你不需要在 CSS 里写 width: 100%; height: auto; 去“猜”图片怎么显示,而是直接用 background-size: cover 或 object-fit: contain 精准控制。这就是专业前端和“能跑就行”的本质区别:前者让资源为设计服务,后者让设计为资源妥协。
4. 实操过程与核心环节实现:手把手带你写出一个“会呼吸”的响应式导航栏
现在,让我们真正动手,以首页导航栏(<header>)为例,走完从 HTML 结构到 CSS 响应式再到 JS 交互的完整闭环。打开 index.html,找到 <header> 标签内的内容:
<header class="site-header">
<div class="header-container">
<a href="index.html" class="logo">
<img src="xiaomi.png" alt="小米商城">
</a>
<nav class="main-nav">
<ul class="nav-list">
<li class="nav-item"><a href="index.html" class="nav-link active">首页</a></li>
<li class="nav-item"><a href="search.html" class="nav-link">搜索</a></li>
<li class="nav-item"><a href="#" class="nav-link">分类</a></li>
<li class="nav-item"><a href="#" class="nav-link">发现</a></li>
</ul>
</nav>
<div class="header-actions">
<a href="#" class="action-icon search-icon" title="搜索"><img src="search.png" alt="搜索"></a>
<a href="#" class="action-icon cart-icon" title="购物车"><img src="car.png" alt="购物车"></a>
<a href="#" class="action-icon user-icon" title="我的"><img src="icon.png" alt="我的"></a>
</div>
</div>
</header>
这段 HTML 的精妙之处在于语义与结构的双重胜利。<header> 是页面一级语义容器;<nav> 明确标识导航区域;<ul> + <li> 是导航菜单的标准结构;每个 <a> 的 href 属性真实指向页面(index.html、search.html),保证了无 JS 时的基础可用性。接下来,打开 indexStyle.css,找到 .site-header 相关样式:
.site-header {
position: sticky;
top: 0;
z-index: 1000;
background: #fff;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.header-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
}
.logo img {
height: 24px;
vertical-align: middle;
}
.main-nav .nav-list {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.main-nav .nav-item {
margin: 0 15px;
}
.main-nav .nav-link {
text-decoration: none;
color: #333;
font-size: 14px;
padding: 8px 12px;
border-radius: 4px;
transition: all 0.3s ease;
}
.main-nav .nav-link:hover,
.main-nav .nav-link.active {
background: #ff6700;
color: #fff;
}
这里的关键参数计算值得深挖。.header-container 的 height: 60px 不是拍脑袋定的,它等于 Logo 图片高度(24px)+ 上下内边距(8px * 2)+ 行高余量(10px),确保文字垂直居中不溢出;.nav-link 的 padding: 8px 12px 让点击热区足够大(移动端最小触控尺寸 44px * 44px),而 border-radius: 4px 是小米 UI 的标志性圆角。现在,重点来了:响应式断点。继续在 indexStyle.css 里找到媒体查询:
/* 平板及以下设备 */
@media screen and (max-width: 768px) {
.header-container {
padding: 0 15px;
height: 56px;
}
.logo img {
height: 22px;
}
.main-nav .nav-list {
display: none; /* 隐藏桌面端导航 */
}
.header-actions .search-icon {
display: block;
}
.mobile-menu-toggle {
display: block;
}
}
注意,这段代码里其实埋了一个“未完成项”:.mobile-menu-toggle 类在 HTML 中并不存在!这是故意留的钩子,让你在 indexJs.js 里补全移动菜单逻辑。实操时,你需要在 <header> 内 <div class="header-actions"> 前插入:
<button class="mobile-menu-toggle" aria-label="打开菜单">
<span></span>
<span></span>
<span></span>
</button>
然后在 indexJs.js 里写:
$(document).ready(function() {
$('.mobile-menu-toggle').click(function() {
$('.main-nav .nav-list').slideToggle(300);
});
});
最后,给 .mobile-menu-toggle 加上 CSS(在 indexStyle.css 底部):
.mobile-menu-toggle {
display: none;
flex-direction: column;
justify-content: space-between;
width: 24px;
height: 18px;
cursor: pointer;
}
.mobile-menu-toggle span {
width: 100%;
height: 2px;
background: #333;
transition: all 0.3s ease;
}
/* 旋转动画 */
.mobile-menu-toggle.active span:nth-child(1) {
transform: rotate(45deg) translate(5px, 5px);
}
.mobile-menu-toggle.active span:nth-child(2) {
opacity: 0;
}
.mobile-menu-toggle.active span:nth-child(3) {
transform: rotate(-45deg) translate(5px, -5px);
}
这个过程完整展示了“小米风格”的实现逻辑:结构先行(HTML 语义化),样式驱动(CSS 精细控制尺寸与动效),交互点睛(JS 补全缺失环节)。你写的不是一堆代码,而是一个会随屏幕宽度“呼吸”、在移动端展开汉堡菜单、悬停时有微妙渐变的活体组件。我实测过,当学员第一次看到自己写的导航栏在手机模拟器里流畅展开时,那种“我造出来了”的兴奋感,远胜于任何框架教程。
5. 商品详情页深度拆解:规格选择器、图片画廊与加入购物车的协同逻辑
商品详情页(product.html)是整个实战包的技术制高点,它把静态页面推向了轻交互应用。打开 product.html,你会看到一个典型的电商详情结构:顶部轮播图占位区、商品标题与价格、规格选择器(颜色、内存)、图文详情、底部固定购买栏。我们聚焦三个核心交互模块:规格选择器、图片画廊、加入购物车按钮,看它们如何通过数据绑定协同工作。
首先,规格选择器的 HTML 结构:
<div class="product-specs">
<h3>选择规格</h3>
<div class="spec-group">
<label class="spec-label">颜色</label>
<div class="spec-options">
<button type="button" class="spec-btn active" data-spec="color" data-value="black">黑色</button>
<button type="button" class="spec-btn" data-spec="color" data-value="white">白色</button>
<button type="button" class="spec-btn" data-spec="color" data-value="blue">蓝色</button>
</div>
</div>
<div class="spec-group">
<label class="spec-label">内存</label>
<div class="spec-options">
<button type="button" class="spec-btn active" data-spec="memory" data-value="128GB">128GB</button>
<button type="button" class="spec-btn" data-spec="memory" data-value="256GB">256GB</button>
</div>
</div>
</div>
这里的 data-spec 和 data-value 属性是关键。它不依赖任何框架,仅用原生 HTML 数据属性就建立了“用户选择”与“商品属性”的映射关系。在 indexJs.js 中,你可以这样监听选择:
// 规格选择逻辑
$('.spec-btn').click(function() {
const $this = $(this);
const specType = $this.data('spec'); // 'color' or 'memory'
const specValue = $this.data('value'); // 'black', '128GB', etc.
// 移除同类型其他按钮的 active 类
$(`.spec-btn[data-spec="${specType}"]`).removeClass('active');
// 给当前按钮添加 active 类
$this.addClass('active');
// 更新图片画廊(根据颜色)
if (specType === 'color') {
updateProductGallery(specValue);
}
// 更新价格(假设不同内存价格不同)
if (specType === 'memory') {
updateProductPrice(specValue);
}
});
updateProductGallery() 函数会根据 specValue 切换轮播图占位区的背景图,比如 black 对应 product-black.jpg,white 对应 product-white.jpg。而 updateProductPrice() 则从一个预设对象中读取价格:
const productPrices = {
'128GB': '2499',
'256GB': '2799'
};
再看图片画廊,它并非真正的轮播图,而是一个带缩略图的静态画廊(为降低初学者复杂度):
<div class="product-gallery">
<div class="gallery-main">
<img src="picture.png" alt="商品主图" class="main-img">
</div>
<div class="gallery-thumbs">
<img src="picture.png" alt="主图缩略图" class="thumb active">
<img src="video.png" alt="视频缩略图" class="thumb">
<img src="repair.png" alt="售后缩略图" class="thumb">
</div>
</div>
缩略图点击切换主图的逻辑,同样写在 indexJs.js:
$('.gallery-thumbs .thumb').click(function() {
const $this = $(this);
const newSrc = $this.attr('src');
$('.gallery-thumbs .thumb').removeClass('active');
$this.addClass('active');
$('.gallery-main .main-img').attr('src', newSrc);
});
最后,加入购物车按钮的状态管理,是体现“协同逻辑”的高潮:
<div class="buy-bar">
<div class="price">¥<span id="current-price">2499</span></div>
<button id="add-to-cart" class="btn-buy" disabled>加入购物车</button>
</div>
它的 disabled 状态由规格选择决定。在 indexJs.js 的规格选择函数末尾,加上:
// 检查是否所有规格都已选择
function checkSpecsComplete() {
const colorSelected = $('.spec-btn[data-spec="color"].active').length > 0;
const memorySelected = $('.spec-btn[data-spec="memory"].active').length > 0;
if (colorSelected && memorySelected) {
$('#add-to-cart').prop('disabled', false);
} else {
$('#add-to-cart').prop('disabled', true);
}
}
// 在每次规格点击后调用
checkSpecsComplete();
这个设计的精妙在于:它没有用全局变量存储状态,而是实时查询 DOM 元素的 active 类存在与否,确保了状态与视图的严格同步。当你点击“黑色”和“128GB”后,按钮立即变亮;若你取消“黑色”选择,按钮瞬间禁用。这种即时反馈,正是用户感知“系统可靠”的心理基础。我曾让学员对比两种写法:一种是用 let selectedColor = '' 存状态,另一种是直接查 DOM。前者在多次操作后容易因忘记更新变量而失步,后者则天然免疫。真正的前端工程,往往藏在这些看似“笨拙”的实时查询里。
6. 常见问题与排查技巧实录:那些只有亲手敲过才会遇到的“幽灵 Bug”
即使是一套“开箱即用”的练习包,实操中也会冒出各种意料之外的问题。这些不是缺陷,而是真实开发场景的浓缩。以下是我在指导学员过程中,高频出现的六大“幽灵 Bug”及其排查心法,附带真实现场记录。
6.1 问题:双击 index.html 打开,轮播图占位区一片空白,控制台报错 Failed to load resource: net::ERR_FILE_NOT_FOUND,但 picture.png 明明就在同一目录!
排查过程:
- 第一步,右键检查元素,定位到轮播图 <div class="banner-placeholder">,查看其 background-image CSS 声明。
- 发现 url('picture.png') 路径正确,但浏览器地址栏显示 file:///Users/xxx/workspace/index.html,而图片实际在 file:///Users/xxx/workspace/assets/images/picture.png。
- 根源:初学者常忽略 file:// 协议下,相对路径的基准是当前 HTML 文件所在目录,而非 CSS 文件所在目录。indexStyle.css 里写的 url('picture.png'),浏览器会去 index.html 同级找,而非 indexStyle.css 同级。
解决方案:
- 统一资源路径基准。在 indexStyle.css 中,将所有图片路径改为相对于 HTML 的路径:url('assets/images/picture.png')。
- 或者,更优方案:在 index.html 的 <head> 中添加 <base href="./">,强制所有相对路径以 HTML 为基准。
提示:这个 Bug 的教训是——永远不要假设路径“应该”是对的,用浏览器开发者工具的 Network 面板,看浏览器实际请求的 URL 是什么,比猜一百次都准。
6.2 问题:在 search.html 中输入文字,热搜词列表不更新,indexJs.js 里的 $("#search-input").on("input", ...) 事件完全没触发。
排查过程:
- 第一步,检查 search.html 中搜索框的 id 是否为 search-input。发现写成了 id="searchInput"(驼峰命名),而 JS 里写的是 #search-input(短横线)。
- 第二步,检查 jQuery 是否加载成功。在控制台输入 $,返回 function,说明 jQuery 加载正常。
- 第三步,检查事件绑定时机。发现 indexJs.js 在 <body> 底部加载,但 $("#search-input") 查询时,DOM 尚未渲染完毕(因为 search.html 的 <input> 在 <body> 中部)。
解决方案:
- 修正 HTML 中的 id 为 search-input。
- 在 indexJs.js 中,将事件绑定包裹在 $(document).ready(...) 内,确保 DOM 加载完成后再执行:
javascript $(document).ready(function() { $("#search-input").on("input", function() { // 你的逻辑 }); });
注意:jQuery 的
$(...)本身有文档就绪检测,但显式写$(document).ready是更稳妥的习惯,尤其当 JS 文件放在<head>时。
6.3 问题:product.html 中规格按钮点击后,active 类能正确切换,但加入购物车按钮始终 disabled,checkSpecsComplete() 函数里 console.log(colorSelected) 输出 false。
排查过程:
- 第一步,检查按钮的 data-spec 属性值。发现 data-spec="color" 写成了 data-spec="Color"(首字母大写)。
- 第二步,检查 checkSpecsComplete() 函数中的选择器:$(.spec-btn[data-spec=”color”]) 是小写,而 DOM 中是大写,导致 jQuery 查不到元素。
- 第三步,验证:在控制台手动执行 $(.spec-btn[data-spec=”Color”]),返回 3 个元素;执行 $(.spec-btn[data-spec=”color”]),返回 0。
解决方案:
- 统一 data-* 属性命名规范:全部小写,用短横线分隔(data-spec-type),避免大小写敏感陷阱。
- 在 indexJs.js 中,将选择器改为 $(.spec-btn[data-spec=”Color”]),或更推荐——修正 HTML 中的属性值为小写。
| 问题现象 | 根本原因 | 快速自查命令 |
|---|---|---|
| 图片不显示 | file:// 协议下路径基准混乱 | Network 面板看请求 URL |
| 事件不触发 | DOM 元素 ID/Class 名不一致或加载时机错误 | console.log($("#your-id").length) |
| 数据属性失效 | data-* 属性大小写不匹配 | console.log($("button").data("spec")) |
6.4 问题:在 Chrome 浏览器中一切正常,但用 Safari 打开 index.html,导航栏的 position: sticky 失效,滚动时导航栏不固定。
排查过程:
- 第一步,查阅 CanIUse,确认 position: sticky 在 Safari 中支持,但需要 -webkit-sticky 前缀。
- 第二步,检查 indexStyle.css,发现只写了 position: sticky;,缺少前缀。
解决方案:
- 在 .site-header 样式中,补充浏览器前缀:
css .site-header { position: -webkit-sticky; position: sticky; top: 0; }
- 更彻底的方案:使用 Autoprefixer 工具自动添加前缀,但本练习包为零依赖,手动添加是最直接的学习。
6.5 问题:修改了 product.css 中 .spec-btn 的 background-color,保存后刷新页面,颜色没变,清空缓存也没用。
排查过程:
- 第一步,检查 product.html 中 <link> 标签的 href 是否指向 product.css。发现写成了 href="productStyle.css"(多写了 Style)。
- 第二步,检查文件编码。用 VS Code 打开 product.css,右下角显示 UTF-8,正常。
- 第三步,检查 CSS 优先级。发现 indexStyle.css 中也有 .spec-btn 样式,且 indexStyle.css 在 product.css 之后加载,覆盖了新样式。
解决方案:
- 修正 HTML 中的 <link> 标签 href 为 product.css。
- 或者,调整 CSS 加载顺序:将 product.css 放在 indexStyle.css 之后,利用层叠规则。
6.6 问题:在 search.html 中,点击热搜词 <a> 标签,页面跳转到了 https://www.baidu.com/s?wd=小米手机,但 indexJs.js 里明明写了 event.preventDefault()。
排查过程:
- 第一步,检查 indexJs.js 中事件绑定的元素选择器。发现写的是 $(".hot-search a"),但 search.html 中热搜词结构是 <div class="hot-search"><a href="...">小米手机</a></div>,选择器正确。
- 第二步,检查 event.preventDefault() 是否在回调函数中执行。发现代码写成了:
javascript $(".hot-search a").click(function(event) { console.log("clicked"); }); event.preventDefault(); // 错误!这行在函数外部,永远不执行
解决方案:
- 将 event.preventDefault() 移入回调函数内部:
javascript $(".hot-search a").click(function(event) { event.preventDefault(); console.log("clicked"); });
实操心得:这类 Bug 最难调试,因为控制台不报错,行为却不符合预期。养成习惯:只要涉及
preventDefault或stopPropagation,第一时间检查它是否在事件回调函数作用域内。
7. 从练习到实战:如何用这个包搭建你的第一个作品集项目
这套三页仿写包的价值,远不止于“练手”。它是一块跳板,帮你把零散技能焊接到真实项目中。我建议你按以下三步,把它升级为你的前端作品集亮点:
第一步:注入真实数据,告别占位符
把 index.html 里轮播图的 picture.png 替换成小米官网真实的手机主图(注意版权,仅用于学习展示);把商品卡片中的 15.png、7.png 替换成你从公开渠道获取的、符合小米风格的手机、耳机、手环产品图;在 search.html 的热搜词列表里,填入真实的“小米14”、“Redmi Note 13”等关键词。这个过程强迫你处理真实图片的尺寸裁剪、格式转换(WebP)、Alt 文本优化,这些都是面试官会追问的细节。
第二步:增加一个“轻量级功能”,证明你的工程能力
选一个痛点下手:比如在 product.html 中,为图片画廊添加键盘方向键支持(← → 切换缩略图),只需在 indexJs.js 中加几行:
$(document).keydown(function(e) {
if ($('.product-gallery').is(':visible')) {
if (e.key === 'ArrowLeft') {
// 上一张缩略图
} else if (e.key === 'ArrowRight') {
// 下一张缩略图
}
}
});
或者,在 search.html 中,为搜索框添加本地存储历史记录:
$("#search-input").on("change", function() {
const keyword = $(this).val().trim();
if (keyword) {
let history = JSON.parse(localStorage.getItem("searchHistory") || "[]");
history.unshift(keyword);
history = [...new Set(history)].slice(0, 5); // 去重并限制5条
localStorage.setItem("searchHistory", JSON.stringify(history));
}
});
这种“小而美”的功能,比写十个 alert 更能体现你的产品思维。
第三步:写一份《重构手记》,成为作品集的灵魂
不要只放代码链接。用 Markdown 写一篇 500 字的《重构手记》,记录你在这个包上的真实思考:
- “我最初以为轮播图要用 JS 写,后来发现小米官网用的是 CSS @keyframes 动画,于是重写了 banner-placeholder 的动画逻辑。”
- “在调试 Safari sticky 失效时,我学会了用 CanIUse 查兼容性,并理解了浏览器前缀的历史意义。”
- “我把所有图片移到 assets/images/ 后,意识到路径管理是团队协作的第一道防火墙。”
这份手记,才是你区别于“只会抄代码”的关键证据。我见过太多学员,作品集里全是炫酷的 Vue 项目,但当被问到“你如何保证图片在弱网下快速加载”时哑口无言。而一个认真写过《重构手记》的人,已经站在了工程实践的起点。
最后再分享一个小技巧:把这个包的所有文件,连同你的修改记录,一起推送到 GitHub。在仓库 README.md 里,用一句话描述它:“一个从零开始的小米商城界面仿写项目,包含首页、搜索页、商品详情页,所有代码纯手写,无框架依赖,专注 HTML/CSS/JS 基础能力锤炼。” 然后,在你的简历“项目经验”栏,把这句话原封不动贴上去。面试官扫一眼,就知道你不是一个被框架宠坏的新手,而是一个愿意俯身触摸像素、理解每一行代码重量的实践者。
简介:直接可用的小米商城风格前端练习项目,包含三个独立页面:首页(index.html)、搜索页(search.html)、商品详情页(product.html),每个页面配专属CSS文件(indexStyle.css、search.css、product.css)和基础交互脚本(indexJs.js + jquery-3.3.1.js)。采用语义化HTML5编写,实现响应式导航栏、轮播图占位区、商品卡片列表、搜索框组件、底部版权栏等典型电商模块。内置全部所需图片资源,如xiaomi.png、search.png、house.png、car.png、like.png、wechat.png、sina.png、icon.png等共20余张,覆盖图标、按钮、示意图形等场景;另附销售流程图(saleprocess.png)及界面参考图(picture.png、video.png)。所有代码无框架依赖,结构清晰分层,支持双击直接在浏览器中运行,适合HTML/CSS初学者动手练习页面结构拆分、样式组织与基础交互实现。

470

被折叠的 条评论
为什么被折叠?



