Web APIs 入门到实战(day5):解决数据丢失痛点——JS 本地存储 + BOM 操作实战案例(实现数据持久化学生就业表)

        在 JavaScript 学习中,Web APIs 是连接语法与实际开发的关键桥梁。第 5 天的学习聚焦 BOM 操作与本地存储核心技能,不仅能让我们灵活操控浏览器窗口,还能实现数据持久化存储,最终独立完成学生就业表的开发。本文将从基础概念到实战案例,系统梳理知识点,助力快速掌握核心技能。

一、JavaScript 的组成与执行机制

要学好 BOM 操作,首先得明确它在 JS 体系中的位置,以及 JS 的执行逻辑,这是后续开发的基础。

1. JS 的三大核心组成

JavaScript 之所以能实现交互功能,核心由三部分构成:

  • ECMAScript:JS 的语法核心,定义了变量、循环、对象等基础语法规则。
  • DOM:文档对象模型,提供操作 HTML 文档元素的 API,比如修改节点内容、样式等。
  • BOM:浏览器对象模型,提供操作浏览器窗口的 API,比如控制地址栏、定时器等。

2. JS 单线程执行机制

JS 是单线程语言,同一时间只能执行一个任务,这就导致了任务需要排队执行。为了解决 “长时间任务阻塞页面” 的问题,JS 将任务分为两类:

  • 同步任务:在主线程执行栈中顺序执行,前一个任务完成后才执行下一个。
  • 异步任务:不阻塞主线程,先提交到 Web API 进程处理,完成后进入任务队列等待,主线程空闲时再执行。
    • 常见类型:点击 /resize 等普通事件、load/error 等资源加载事件、setTimeout/setInterval 定时器。
  • 执行流程:先执行执行栈中的同步任务 → 异步任务完成后推入任务队列 → 同步任务执行完毕,按顺序读取任务队列中的异步任务,推入执行栈执行(循环往复)。

二、BOM 核心操作:掌控浏览器窗口

BOM(Browser Object Model)即浏览器对象模型,核心是window全局对象,所有 BOM 属性和方法都挂载在window上,调用时可省略window前缀。

1. window 对象:JS 的顶级对象

  • window是全局对象,所有全局变量、函数都会自动成为其属性和方法。
  • 常见的documentalert()console.log()等,本质都是window的属性。

2. 定时器:控制代码执行时机

定时器是 BOM 中最常用的功能,分为延迟执行和间歇执行两类:

  • 延迟函数 setTimeout:延迟指定时间后执行一次回调函数。
    • 语法:const timerId = setTimeout(回调函数, 延迟毫秒数)
    • 核心特点:返回正整数定时器编号,仅执行一次;延迟期间后续代码正常执行。
    • 清除方法:clearTimeout(timerId)(通过编号取消定时器)。
  • 间歇函数 setInterval:每隔指定时间重复执行回调函数(本文重点聚焦延迟函数,间歇函数用法类似)。
// 示例:3秒后执行一次回调,随后取消(实际开发可根据需求调整)
let timerId = setTimeout(() => {
  console.log('延迟3秒执行,仅执行一次');
}, 3000);
// 如需取消,调用clearTimeout(timerId)

3. location 对象:操控浏览器地址栏

   location对象存储了 URL 的完整信息,可实现地址跳转、参数获取等功能,核心属性和方法如下:

属性 / 方法说明
href获取完整 URL,赋值可实现页面跳转(如location.href = "https://www.baidu.com"
search获取 URL 中?后的参数(如?username=zhangsan&age=20
hash获取 URL 中#后的哈希值(常用于单页应用路由,如#user
reload()刷新当前页面,传入true表示强制刷新(类似 Ctrl+F5)
// 示例:获取参数与刷新页面
console.log(location.search); // 打印URL参数
const refreshBtn = document.querySelector('.refresh');
refreshBtn.addEventListener('click', () => {
  location.reload(true); // 强制刷新
});

4. navigator 对象:识别浏览器环境

navigator对象记录了浏览器的核心信息,常用userAgent属性检测设备类型,实现 PC / 移动端页面适配:

// 示例:检测设备并跳转对应站点
(function () {
  const userAgent = navigator.userAgent;
  const isMobile = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/) || userAgent.match(/(iPhone\sOS)\s([\d_]+)/);
  if (isMobile) {
    location.href = 'http://m.itcast.cn'; // 移动端跳转移动站点
  }
})();

5. history 对象:管理浏览器历史记录

history对象对应浏览器地址栏的前进、后退操作,常用方法:

  • back():后退一页(等价于history.go(-1))。
  • forward():前进一页(等价于history.go(1))。
  • 适用场景:OA 系统、后台管理系统等需要历史记录导航的场景。

三、本地存储:实现数据持久化的核心方案

        本地存储能将数据保存在浏览器中,即使页面刷新或关闭,数据也不会丢失,是实现 “页面刷新数据不丢” 的关键技术,容量约 5M,满足大部分前端存储需求。

1. 两种本地存储方案对比

特性localStorage(重点)sessionStorage(了解)
存储周期永久存储,除非手动删除会话级存储,关闭浏览器窗口后清除
共享范围同一浏览器同源页面共享仅当前窗口 / 标签页共享
核心用法存储长期有效数据(如用户偏好、就业表数据)存储临时数据(如表单临时输入)

2. localStorage 基础用法

localStorage键值对形式存储,且仅支持字符串类型数据,核心语法:

  • 存储数据:localStorage.setItem('key', 'value')
  • 获取数据:localStorage.getItem('key')
  • 删除数据:localStorage.removeItem('key')
  • 修改数据:重新调用setItem,覆盖原有 key 的值
// 示例:存储、获取、修改用户信息
// 存储
localStorage.setItem('uname', 'pink老师');
localStorage.setItem('age', '18'); // 数字也会自动转为字符串
// 获取
console.log(localStorage.getItem('uname')); // 输出:pink老师
// 修改
localStorage.setItem('uname', 'red老师');
// 删除
// localStorage.removeItem('age');

3. 存储复杂数据类型(关键技巧)

localStorage仅支持字符串存储,若要存储对象、数组等复杂数据类型,需通过JSON进行转换:

  • 存储时:用JSON.stringify(复杂数据)将其转为 JSON 字符串。
  • 获取时:用JSON.parse(JSON字符串)将其转回原数据类型。

JSON 字符串规则:属性名和字符串类型的属性值必须用双引号包裹。

// 示例:存储对象类型数据
const student = {
  uname: '张三',
  age: 22,
  major: '计算机科学',
  isEmployed: false
};
// 存储:转为JSON字符串
localStorage.setItem('student', JSON.stringify(student));
// 获取:转回对象
const getStudent = JSON.parse(localStorage.getItem('student'));
console.log(getStudent.major); // 输出:计算机科学

四、实战必备:数组 map 与 join 方法

开发学生就业表时,需对数组数据进行遍历处理和格式转换,mapjoin是核心工具方法。

1. map 方法:数组映射(有返回值)

map用于遍历数组,对每个元素进行处理后返回新数组,重点在于有返回值(区别于 forEach 的无返回值)。

语法:const 新数组 = 原数组.map((item, index) => { return 处理后的值 })

// 示例1:给数组元素添加后缀
const names = ['pink', 'red', 'blue'];
const newNames = names.map(item => item + '老师');
console.log(newNames); // 输出:['pink老师', 'red老师', 'blue老师']

// 示例2:数组元素数值运算
const scores = [80, 90, 75];
const addScores = scores.map(item => item + 5);
console.log(addScores); // 输出:[85, 95, 80]

2. join 方法:数组转字符串

join将数组元素拼接为字符串,可指定分隔符(默认用逗号分隔)。

语法:const 字符串 = 原数组.join('分隔符')

// 示例:数组元素用不同分隔符拼接
const arr = ['张三', '李四', '王五'];
console.log(arr.join(',')); // 输出:张三,李四,王五
console.log(arr.join('-')); // 输出:张三-李四-王五
console.log(arr.join(''));  // 输出:张三李四王五

3. 补充:对象属性的动态访问

当属性名是变量时,需用对象[变量名]的方式访问属性,而非.语法:

const student = { uname: '张三' };
const attr = 'age';
student[attr] = 22; // 动态添加age属性
console.log(student); // 输出:{ uname: '张三', age: 22 }

五、综合实战:本地存储学生就业表(核心目标)

        结合上述知识点,我们可以实现一个 “数据持久化” 的学生就业表,核心功能:添加学生就业信息、页面刷新数据不丢失、数据展示格式化。

1. 核心思路

  1. 页面结构:设计表单用于输入学生信息(姓名、专业、薪资、就业状态)。
  2. 数据存储:用localStorage存储学生数组,添加新数据时先读取本地存储,再追加新数据并重新存储。
  3. 数据展示:用map方法遍历学生数组,格式化生成 HTML 结构,用join拼接后渲染到页面。
  4. 数据持久化:页面加载时自动读取本地存储数据并渲染。

2. 关键代码实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>学生就业表</title>
  <style>
    table { border-collapse: collapse; width: 80%; margin: 20px auto; }
    th, td { border: 1px solid #333; padding: 8px; text-align: center; }
    form { width: 80%; margin: 20px auto; display: flex; gap: 10px; }
    input, select, button { padding: 8px; flex: 1; }
  </style>
</head>
<body>
  <form id="jobForm">
    <input type="text" name="uname" placeholder="姓名" required>
    <input type="text" name="major" placeholder="专业" required>
    <input type="number" name="salary" placeholder="薪资" required>
    <select name="isEmployed" required>
      <option value="true">已就业</option>
      <option value="false">未就业</option>
    </select>
    <button type="submit">添加</button>
  </form>
  <table>
    <thead><tr><th>姓名</th><th>专业</th><th>薪资</th><th>就业状态</th></tr></thead>
    <tbody id="jobList"></tbody>
  </table>

  <script>
    // 1. 读取本地存储数据
    function getLocalData() {
      const data = localStorage.getItem('studentJobs');
      return data ? JSON.parse(data) : []; // 无数据时返回空数组
    }

    // 2. 保存数据到本地存储
    function saveLocalData(data) {
      localStorage.setItem('studentJobs', JSON.stringify(data));
    }

    // 3. 渲染数据到页面
    function renderData() {
      const data = getLocalData();
      const tbody = document.getElementById('jobList');
      // 用map格式化数据,join拼接为HTML
      const html = data.map(item => `
        <tr>
          <td>${item.uname}</td>
          <td>${item.major}</td>
          <td>${item.salary}元</td>
          <td>${item.isEmployed === 'true' ? '已就业' : '未就业'}</td>
        </tr>
      `).join('');
      tbody.innerHTML = html;
    }

    // 4. 表单提交事件
    document.getElementById('jobForm').addEventListener('submit', (e) => {
      e.preventDefault(); // 阻止表单默认提交
      // 获取表单数据
      const formData = new FormData(e.target);
      const newStudent = {};
      formData.forEach((value, key) => newStudent[key] = value);
      // 读取原有数据,追加新数据
      const data = getLocalData();
      data.push(newStudent);
      // 保存并重新渲染
      saveLocalData(data);
      renderData();
      // 重置表单
      e.target.reset();
    });

    // 页面加载时渲染数据
    window.addEventListener('load', renderData);
  </script>
</body>
</html>

3. 功能说明

  • 表单提交后,新数据会追加到本地存储的数组中。
  • 页面刷新后,会自动读取本地存储数据并渲染表格。
  • 就业状态通过三元表达式转换为中文显示,薪资添加 “元” 单位,格式更友好。

六、总结与拓展

        第 5 天的学习核心是 “操控浏览器” 与 “数据持久化”:BOM 操作让我们能灵活控制浏览器窗口、地址栏、定时器等;本地存储则解决了 “数据临时存储” 的痛点,实现页面刷新数据不丢失。结合数组 map、join 方法,我们成功完成了学生就业表的实战开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值