ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

纯 HTML/CSS/JS 构建离线菜谱知识库

纯 HTML/CSS/JS 构建离线菜谱知识库 简介这是一套基于纯前端技术栈HTML5、CSS3、JavaScript构建的响应式菜谱百科APP源码面向Web前端初学者与移动端开发入门者解决美食类轻应用快速原型开发与静态资源组织实践问题。资源共98个文件含19个HTML页面覆盖首页、分类、详情、搜索、个人中心等完整路由、17个CSS样式文件含Bootstrap框架及自定义主题、9个JavaScript脚本含数据交互、图片懒加载、Tab切换等核心逻辑以及44张高清菜品与UI组件PNG图整体压缩包仅1.52MB轻量易部署。已有333人学习下载适合用于课程设计、毕业设计或前端技能综合实训。读者可直接运行查看完整菜谱分类体系家常菜、快手菜、素菜、汤粥、面食等、掌握多页面单页应用式结构组织方式并复用其响应式布局、图标字体eot/svg/woff/ttf、表单交互与图片加载优化等典型实践方案。1. 这不是「网页」而是一个可离线运行、带搜索与收藏的菜谱知识库——用纯 HTML/CSS/JavaScript 实现 CookWiki 的核心逻辑你打开一个.html文件没启动任何服务器没装 Node.js没连数据库却能快速检索 200 道菜名、按食材筛选、点击收藏、本地持久化保存、甚至响应式适配手机屏幕——这就是 CookWiki 菜谱百科 APP 的真实交付形态。它不依赖框架、不调用后端 API、不走构建流程所有交互逻辑由原生 JavaScript 驱动样式靠 CSS Grid Flex 布局精准控制结构用语义化 HTML 组织。适合餐饮内容运营者快速搭建内部知识库也适合前端初学者理解「无框架单页应用」如何落地从数据建模JSON 结构设计、DOM 动态渲染不刷新页面更新列表、事件委托处理上百个菜谱卡片的点击、localStorage 封装解决刷新丢失收藏状态到响应式断点控制三行模式的 CSS 文件如何分层管理。本文不讲 React/Vue只拆解一个真实可运行的index.html如何撑起完整功能闭环。2. 用 HTML 语义化结构定义菜谱数据模型与交互入口2.1 为什么必须用articlesection而不是div堆砌CookWiki 的核心是「菜谱即文档」。每道菜不是卡片容器而是独立信息单元。HTML5 语义标签直接映射业务逻辑article表示一道完整菜谱含标题、简介、步骤、小贴士section划分「食材清单」「烹饪步骤」「营养信息」等子模块aside放置「同类推荐」「作者备注」等辅助内容。这种结构让搜索引擎能识别内容层级也让屏幕阅读器准确播报「第3步倒入橄榄油中火加热至冒泡」而非「div 7 里的文字」。更重要的是JavaScript 查询时可直接document.querySelectorAll(article)获取全部菜谱节点无需依赖 class 名或 data 属性——减少 DOM 操作耦合度。提示不要在article内嵌套article。一道菜谱只能有一个顶级 article其子元素用headermainfooter区分结构避免语义污染。2.2 关键 meta 标签决定移动端行为与中文编码稳定性CookWiki 必须在 iOS Safari 和安卓 Chrome 上正确缩放、禁止双击放大、保持 UTF-8 中文不乱码。以下三行meta是硬性配置缺一不可!doctype html html langzh-cn head meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalableno meta namedescription contentCookWiki开源菜谱百科支持搜索、收藏、离线使用 /headcharsetutf-8解决「葱姜蒜」显示为方块的问题这是中文网页的底线viewport中user-scalableno禁用双指缩放防止用户误操作导致布局错位initial-scale1.0强制以 1:1 像素比渲染避免 iOS 默认 320px 宽度拉伸description不仅影响 SEO更在微信内嵌浏览器中决定分享卡片摘要。2.3 数据驱动的 HTML 模板用 script typetext/template 预存渲染结构CookWiki 的菜谱列表、详情页、搜索结果页共用同一套 DOM 结构。为避免重复写 HTML 字符串拼接采用script typetext/template存储模板script typetext/template idrecipe-card-template article classrecipe-card>/* layout.css */ .recipe-grid { display: grid; gap: 1.5rem; } /* 手机默认 1 列 */ .recipe-grid { grid-template-columns: 1fr; } /* 平板及以上2 列 */ media (min-width: 768px) { .recipe-grid { grid-template-columns: repeat(2, 1fr); } } /* 桌面3 列 */ media (min-width: 1200px) { .recipe-grid { grid-template-columns: repeat(3, 1fr); } }gap替代传统margin控制间距避免父子 margin 合并问题repeat(3, 1fr)比auto-fitminmax()更可控确保每列等宽不挤压所有卡片高度由内容决定用align-items: start防止底部对齐导致空白错位。3.3 CSS 鼠标移入事件实现「悬停高亮平滑缩放」的交互反馈菜谱卡片需提供明确视觉反馈。纯 CSS 实现不依赖 JavaScript/* theme.css */ .recipe-card { transition: all 0.3s ease; transform: scale(1); } .recipe-card:hover { box-shadow: 0 8px 24px rgba(0,0,0,0.15); transform: scale(1.02); z-index: 10; } .recipe-card:hover img { transform: scale(1.05); } /* 按钮悬停 */ .btn-detail:hover { background-color: var(--primary); transform: translateY(-2px); }transition: all 0.3s ease控制所有属性过渡避免单独写transform导致其他属性突变z-index: 10确保悬停时卡片浮起不被相邻元素遮挡transform: scale(1.02)比scale(1.1)更克制符合 Material Design 的微交互规范。4. 用原生 JavaScript 实现搜索、收藏与本地持久化核心逻辑4.1 数据初始化从 JSON 数组构建内存数据池支持动态增删CookWiki 的菜谱数据不存服务器而是内置在data/recipes.json中开发时可改为内联 script。加载后解析为内存数组作为所有操作的数据源// data.js const recipes [ { id: chicken-broth, title: 经典鸡汤, category: 汤类, summary: 清甜暖胃适合换季调理, ingredients: [鸡架, 姜片, 枸杞], steps: [冷水下锅焯水, 加足量水炖煮2小时], image: images/chicken.jpg } // ... 其他 199 条 ]; // 初始化时建立索引加速搜索 const recipeIndex new Map(); recipes.forEach(recipe recipeIndex.set(recipe.id, recipe));Map比Object查找快 3 倍V8 引擎优化recipeIndex.get(chicken-broth)直接取对象ingredients数组用于后续「按食材筛选」steps数组支撑步骤展开动画所有 ID 使用短横线命名chicken-broth避免空格或中文导致 CSS 选择器失效。4.2 搜索功能支持标题、食材、步骤的模糊匹配与高亮搜索框输入实时触发不发请求纯前端过滤// search.js function performSearch(query) { if (!query.trim()) return recipes; const lowerQuery query.toLowerCase(); return recipes.filter(recipe recipe.title.toLowerCase().includes(lowerQuery) || recipe.ingredients.some(ing ing.toLowerCase().includes(lowerQuery)) || recipe.steps.some(step step.toLowerCase().includes(lowerQuery)) ); } // 高亮匹配关键词DOM 操作 function highlightText(text, query) { if (!query.trim()) return text; const regex new RegExp((${query}), gi); return text.replace(regex, mark$1/mark); }filter()返回新数组不修改原始recipes保证数据纯净some()检查数组中是否存在匹配项比includes()更语义化mark标签是 HTML5 语义化高亮标签CSS 中统一设置background: yellow即可生效。4.3 收藏状态管理用 localStorage 封装解决刷新丢失问题收藏按钮点击后状态需跨页面保留。封装FavoriteManager类// favorite.js class FavoriteManager { constructor() { this.key cookwiki_favorites; this.favorites this.loadFromStorage(); } loadFromStorage() { try { const data localStorage.getItem(this.key); return data ? JSON.parse(data) : []; } catch (e) { console.warn(读取收藏失败使用空数组, e); return []; } } saveToStorage() { try { localStorage.setItem(this.key, JSON.stringify(this.favorites)); } catch (e) { console.error(保存收藏失败可能超出 5MB 限制, e); } } toggle(id) { const index this.favorites.indexOf(id); if (index -1) { this.favorites.push(id); } else { this.favorites.splice(index, 1); } this.saveToStorage(); } isFavorited(id) { return this.favorites.includes(id); } } const favManager new FavoriteManager();try/catch处理 localStorage 满或禁用的异常场景saveToStorage()在每次toggle()后立即执行确保状态实时落盘isFavorited()供模板渲染时判断按钮状态★ 已收藏/☆ 收藏。5. 优化首屏加载性能与移动端手势体验5.1 关键资源内联把 base.css 和核心 JS 嵌入 HTML 减少请求Lighthouse 评分要求关键 CSS 内联。将base.css内容直接写入style标签核心 JS如FavoriteManager内联至scripthead style :root { --primary: #e74c3c; --spacing-xs: 0.5rem; } * { margin: 0; padding: 0; box-sizing: border-box; } /style script class FavoriteManager { /* ... */ } const favManager new FavoriteManager(); /script /head内联 CSS 不超过 15KB当前 base.css 仅 2.1KB避免阻塞渲染内联 JS 仅包含必需类业务逻辑仍外链app.js平衡首屏与缓存。5.2 移动端手势增强用 touchstart/touchend 替代 click 防止 300ms 延迟iOS Safari 点击有 300ms 延迟影响按钮响应。用touchstart模拟点击// utils.js function addTouchClick(selector, callback) { document.addEventListener(touchstart, e { const target e.target.closest(selector); if (target) { e.preventDefault(); // 阻止默认滚动行为 callback(target); } }, { passive: false }); } // 使用 addTouchClick(.btn-favorite, el { const id el.dataset.id; favManager.toggle(id); el.textContent favManager.isFavorited(id) ? ★ 已收藏 : ☆ 收藏; });passive: false允许preventDefault()否则无法阻止滚动e.target.closest(selector)兼容子元素点击如按钮内图标保留click事件监听器确保桌面端正常工作降级兼容。5.3 图片加载优化用 IntersectionObserver 实现懒加载降低初始负载首页 200 张菜谱图若全部加载首屏时间超 5s。用原生IntersectionObserver// image-loader.js function initLazyLoad() { const observer new IntersectionObserver((entries) { entries.forEach(entry { if (entry.isIntersecting) { const img entry.target; img.src img.dataset.src; img.classList.remove(lazy); observer.unobserve(img); } }); }, { threshold: 0.1 }); document.querySelectorAll(img[data-src]).forEach(img { observer.observe(img); }); } // HTML 中写法img>curl -s http://localhost:8000/index.html | grep -E (article|section|header) | head -5预期输出应包含article classrecipe-card等语义标签证明即使 JS 被禁用基础内容仍可访问。若返回空说明模板未正确注入或路径错误。6.2 用 grep 检查关键 meta 标签是否生效验证移动端适配curl -s http://localhost:8000/index.html | grep -o viewport.*user-scalableno必须输出viewport contentwidthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalableno否则 iOS 双击会放大。6.3 用 localStorage 检查收藏状态持久化在浏览器控制台执行// 清空后测试 localStorage.removeItem(cookwiki_favorites); console.log(localStorage.getItem(cookwiki_favorites)); // null // 添加一个收藏 favManager.toggle(chicken-broth); console.log(JSON.parse(localStorage.getItem(cookwiki_favorites))); // [chicken-broth] // 刷新页面后验证 // → 重新打开页面检查按钮文字是否仍为 ★ 已收藏6.4 用 Lighthouse CLI 批量检测性能指标安装并运行npm install -g lhci lhci collect --urlhttp://localhost:8000 --collect.settings.chromeFlags--no-sandbox --collect.numberOfRuns3 lhci assert --presetlighthouse:recommended重点关注First Contentful Paint 1.5s、Cumulative Layout Shift 0.1、Total Blocking Time 200ms。若 CLS 超标检查图片是否设置width/height属性或aspect-ratio。提示所有检测必须在http://localhost:8000下进行file://协议下 localStorage 和 fetch 会被浏览器策略拦截导致功能失效。推荐用npx serve或 Pythonhttp.server启动本地服务。本文还有配套的精品资源点击获取
返回列表