231 How to Plan a Web Project 笔记

一、项目规划的重要性(核心前提)

1.1 规划的必要性

  • 对复杂项目(如本课程的 Mapty 锻炼记录项目)而言,编码前规划可避免后续代码混乱、功能遗漏等问题。
  • 此前课程项目多直接编码,未深入考虑功能逻辑与架构设计,而实际开发中 “先规划再开发” 是标准流程,能减少返工成本。

1.2 规划的适用场景

  • 适用于中小型 Web 项目(本课程推荐流程),大型项目可在此基础上增加需求评审、技术选型评审等环节。

二、Web 项目规划四步流程(核心方法)

2.1 第一步:定义用户故事(从用户视角明确功能)

2.1.1 用户故事的概念

  • 定义:以用户视角描述应用功能,明确 “谁用、做什么、为什么做”,多个用户故事组合可完整覆盖应用核心能力。
  • 标准格式:作为[某类用户],我想[执行某个动作],以便我可以[获得某种好处]
  • 作用:帮助开发者脱离技术视角,聚焦用户真实需求,避免开发 “无用功能”。

2.1.2 Mapty 项目用户故事实例(结合需求落地)

序号 用户故事内容 对应核心需求
1 作为用户,我想记录跑步锻炼的位置、距离、时间、步速和每分钟步数,以便保存所有跑步记录 跑步数据录入与存储
2 作为用户,我想记录骑行锻炼的位置、距离、时间、速度和海拔增益,以便保存所有骑行记录 骑行数据录入与存储(与跑步差异化字段)
3 作为用户,我想一目了然查看所有锻炼记录,以便跟踪锻炼进度 锻炼记录列表展示
4 作为用户,我想在地图上查看所有锻炼记录,以便了解锻炼集中区域 地图可视化锻炼位置
5 作为用户,我想在离开应用后再次打开时查看之前的锻炼记录,以便持续使用 数据持久化存储

2.1.3 从用户故事推导功能(例题)

  • 例题:基于 “记录跑步锻炼” 的用户故事,推导需实现的具体功能。
  • 解析:
    1. 位置记录:需地图组件(支持点击选择锻炼位置);
    2. 数据录入:需表单(包含距离、时间、步速、每分钟步数输入框);
    3. 定位优化:需地理定位 API(自动获取用户当前位置,渲染中心地图);
    4. 数据保存:需本地存储(临时保存跑步记录,避免页面刷新丢失)。

2.2 第二步:绘制流程图(梳理功能逻辑与数据流向)

2.2.1 流程图的核心要素

  • 包含内容:待实现功能、模块交互关系、触发事件、数据流向。
  • 视觉规范(推荐):
    • 黄色框:用户或系统触发的 “动作”(如 “点击地图”“提交表单”);
    • 绿色框:“界面渲染” 操作(如 “显示地图”“渲染锻炼列表”);
    • 红色框:“异步操作”(如 “调用地理定位 API”“读取本地存储”,需等待结果返回)。

2.2.2 Mapty 项目核心流程实例(分场景梳理)

  1. 页面加载场景
    • 事件触发:页面首次加载 / 刷新;
    • 流程:调用地理定位 API(红色,异步)→ 获取用户坐标 → 渲染中心地图(绿色)→ 读取本地存储锻炼数据(红色,异步)→ 渲染锻炼列表 + 地图标记(绿色)。
  2. 添加锻炼场景
    • 事件触发:用户点击地图;
    • 流程:显示锻炼表单(绿色)→ 用户选择锻炼类型(跑步 / 骑行)并填写数据 → 提交表单(黄色)→ 验证数据 → 渲染锻炼列表 + 地图标记(绿色)→ 保存数据到本地存储(红色,异步)。
  3. 锻炼定位场景
    • 事件触发:用户点击锻炼列表某条记录;
    • 流程:获取该记录的位置坐标(黄色)→ 地图自动定位到对应位置(绿色)。

2.2.3 流程图绘制技巧(避坑指南)

  • 无需追求 “完美初始版本”:先画粗略草图,开发过程中补充细节(如初期可忽略 “数据验证” 步骤,后续完善);
  • 从 “事件” 切入:所有流程以用户操作(点击、提交)或系统事件(页面加载)为起点,避免逻辑混乱;
  • 标注依赖关系:异步操作需明确 “等待结果后执行后续步骤”(如必须先获取定位,才能渲染地图)。

2.3 第三步:规划项目架构(确定代码组织方式)

2.3.1 架构的核心定义

  • 本质:代码的组织形式 + 技术选型(如 “是否用类封装数据”“是否拆分多文件”“是否用框架”),无需过度复杂,以 “可维护、易扩展” 为目标。

2.3.2 中小型项目架构选择(推荐方案)

  • 基础架构(适合本课程 Mapty 项目):
    1. 按 “功能模块” 拆分函数:
      • 地图模块:initMap()(初始化地图)、addMarker()(添加锻炼标记);
      • 表单模块:showForm()(显示表单)、validateForm()(验证数据);
      • 存储模块:saveToLocalStorage()(保存数据)、getFromLocalStorage()(读取数据)。
    2. 用 “类” 封装锻炼数据(可选,提升代码复用):
      • 定义Workout父类,包含共同属性(位置、距离、时间)和方法(save());
      • 定义RunningCycling子类,扩展差异化属性(跑步的 “步速”、骑行的 “海拔增益”)。

2.3.3 架构规划误区(例题:反例分析)

  • 反例:将所有代码写在一个script标签中,无函数拆分,直接用全局变量存储锻炼数据(如let workouts = [])。
  • 问题:
    1. 全局变量污染:若引入其他脚本,可能覆盖workouts
    2. 维护困难:代码超过 500 行后,无法快速定位 “添加锻炼” 或 “保存数据” 的逻辑;
    3. 扩展性差:后续新增 “锻炼数据编辑” 功能,需修改大量原有代码。
  • 改进方案:用 IIFE(立即执行函数)包裹代码,避免全局变量;按模块拆分函数,如将 “存储相关” 逻辑单独封装。

2.4 第四步:进入开发阶段(落地规划)

2.4.1 开发前的准备

  • 技术确认:明确依赖的 API 或库(如 Mapty 项目需 “Leaflet 地图库”“地理定位 API”“localStorage”);
  • 资源准备:获取第三方库 CDN 链接(如 Leaflet 的 CSS 和 JS 文件)、定义数据格式(如锻炼记录的 JSON 结构:{type: "running", distance: 5, time: 30, coords: {lat: 30.123, lng: 120.456}})。

2.4.2 开发与规划的联动

  • 开发中若发现规划漏洞(如表单未考虑 “数据格式错误”),需回溯调整流程图和架构(如新增validateForm()函数,补充 “数据验证失败→提示用户” 流程);
  • 优先实现 “核心功能”:先完成 “添加锻炼 + 显示地图”,再优化 “数据持久化”“列表点击定位” 等次要功能。