HTML5 入门到高阶的10个场景实战

4 阅读1分钟

1. HTML5 语义化页面开发

应用场景:搭建企业官网 / 博客的基础结构,替代纯 div 布局,提升 SEO 和可读性。

核心知识点:header/nav/main/article/section/aside/footer 语义标签、meta 适配移动端。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <!-- 移动端适配核心:视口宽度=device-width,缩放1 -->
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML5 语义化官网</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: "微软雅黑", sans-serif; }
    header, nav, footer { padding: 15px; background: #333; color: #fff; }
    nav ul { display: flex; list-style: none; gap: 20px; }
    nav a { color: #fff; text-decoration: none; }
    main { display: flex; padding: 20px; gap: 20px; }
    article { flex: 3; }
    aside { flex: 1; background: #f5f5f5; padding: 15px; }
    section { margin-bottom: 20px; padding: 15px; border: 1px solid #eee; }
  </style>
</head>
<body>
  <!-- 头部:品牌/标题 -->
  <header>
    <h1>XX科技官网</h1>
  </header>

  <!-- 导航栏:核心导航 -->
  <nav>
    <ul>
      <li><a href="#home">首页</a></li>
      <li><a href="#product">产品</a></li>
      <li><a href="#about">关于我们</a></li>
    </ul>
  </nav>

  <!-- 主体内容:页面核心 -->
  <main>
    <!-- 主要内容区 -->
    <article>
      <section id="home">
        <h2>首页介绍</h2>
        <p>HTML5 语义化让页面结构更清晰,搜索引擎更易识别内容。</p>
      </section>
      <section id="product">
        <h2>核心产品</h2>
        <p>基于 HTML5 开发的跨端应用,兼容多设备。</p>
      </section>
    </article>

    <!-- 侧边栏:辅助信息 -->
    <aside>
      <h3>联系方式</h3>
      <p>电话:123456789</p>
      <p>邮箱:test@xxx.com</p>
    </aside>
  </main>

  <!-- 底部:版权/备案 -->
  <footer>
    <p>© 2026 XX科技 版权所有 | 备案号:粤ICP备XXXX号</p>
  </footer>
</body>
</html>

关键解析

 main  标签代表页面唯一核心内容,一个页面仅一个;

 meta:viewport 是移动端适配的基础,必须添加;

 语义标签不影响样式,需配合 CSS 实现布局,核心是「结构语义化」而非「样式语义化」。

2. HTML5 新表单控件实战(简化表单开发)

应用场景:开发注册 / 登录 / 信息收集表单,利用 HTML5 原生控件减少 JS 开发量。

核心知识点

input 新类型(date/email/number)、

required/pattern/placeholder 属性、

datalist 联想输入。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML5 新表单实战</title>
  <style>
    form { max-width: 500px; margin: 20px auto; padding: 20px; border: 1px solid #eee; }
    .form-item { margin-bottom: 15px; }
    label { display: block; margin-bottom: 5px; }
    input, select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; }
    button { padding: 10px 20px; background: #007bff; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
  </style>
</head>
<body>
  <form action="#" method="post">
    <div class="form-item">
      <label for="email">邮箱(原生验证):</label>
      <input type="email" id="email" required placeholder="请输入邮箱">
    </div>
    <div class="form-item">
      <label for="phone">手机号(正则验证):</label>
      <input type="tel" id="phone" required pattern="^1[3-9]\d{9}$" placeholder="请输入手机号">
    </div>
    <div class="form-item">
      <label for="age">年龄(数字限制):</label>
      <input type="number" id="age" min="18" max="60" placeholder="18-60岁">
    </div>
    <div class="form-item">
      <label for="birthday">生日:</label>
      <input type="date" id="birthday">
    </div>
    <div class="form-item">
      <label for="city">城市(联想输入):</label>
      <input type="text" id="city" list="cityList" placeholder="输入或选择城市">
      <datalist id="cityList">
        <option value="北京"></option>
        <option value="上海"></option>
        <option value="广州"></option>
      </datalist>
    </div>
    <button type="submit">提交</button>
  </form>
</body>
</html>

关键解析

 required:标记必填项,提交时原生验证;

 pattern:自定义正则验证(如手机号),无需手写 JS 验证;

 type=email/number/date:浏览器原生适配输入样式(如日期选择器),提升用户体验。

3. HTML5 多媒体(音频 / 视频)开发

应用场景

开发视频播放页、音频播放器,替代 Flash,原生支持多格式。

核心知识点

video/audio 标签、controls/autoplay/muted/loop 属性、多格式兼容。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML5 多媒体实战</title>
  <style>
    .media-box { max-width: 800px; margin: 20px auto; }
    video { width: 100%; border: 1px solid #eee; }
    audio { width: 100%; margin-top: 20px; }
  </style>
</head>
<body>
  <div class="media-box">
    <h3>视频播放(多格式兼容)</h3>
    <!-- poster:视频封面;controls:原生控制栏;muted+autoplay:静音自动播放(浏览器允许) -->
    <video 
      poster="cover.jpg" 
      controls 
      muted 
      preload="metadata"
    >
      <!-- 多格式兼容:浏览器自动选择支持的格式 -->
      <source src="video.mp4" type="video/mp4">
      <source src="video.webm" type="video/webm">
      您的浏览器不支持 HTML5 视频播放,请升级浏览器!
    </video>

    <h3>音频播放</h3>
    <audio controls loop>
      <source src="music.mp3" type="audio/mpeg">
      <source src="music.ogg" type="audio/ogg">
      您的浏览器不支持 HTML5 音频播放!
    </audio>
  </div>
</body>
</html>

关键解析: 

preload="metadata":仅预加载视频元数据(时长 / 封面),不加载完整视频,节省带宽; 

autoplay 需配合 muted:多数浏览器禁止非静音自动播放;

多 source 标签:兼容不同浏览器(如 MP4 兼容主流浏览器,WebM 兼容火狐 / Chrome)。

4. localStorage 本地存储实战(数据持久化)

应用场景:开发「用户偏好设置」「草稿箱」「历史记录」,无需后端实现数据本地保存。 

核心知识点:localStorage 增删改查、JSON 序列化 / 反序列化、数据过期处理。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>localStorage 实战</title>
  <style>
    .demo-box { max-width: 500px; margin: 20px auto; padding: 20px; border: 1px solid #eee; }
    textarea { width: 100%; height: 100px; margin: 10px 0; padding: 8px; }
    button { margin-right: 10px; padding: 8px 15px; cursor: pointer; }
  </style>
</head>
<body>
  <div class="demo-box">
    <h3>本地草稿箱(关闭页面不丢失)</h3>
    <textarea id="content" placeholder="输入内容,自动保存草稿..."></textarea>
    <button onclick="saveDraft()">手动保存</button>
    <button onclick="clearDraft()">清空草稿</button>
    <p id="tip"></p>
  </div>

  <script>
    const contentEl = document.getElementById('content');
    const tipEl = document.getElementById('tip');
    const STORAGE_KEY = 'article_draft';

    // 页面加载时读取草稿
    window.onload = function() {
      const draft = localStorage.getItem(STORAGE_KEY);
      if (draft) {
        contentEl.value = draft;
        tipEl.innerText = '已加载本地草稿';
      }
    };

    // 实时保存(输入时自动保存)
    contentEl.addEventListener('input', function() {
      localStorage.setItem(STORAGE_KEY, this.value);
      tipEl.innerText = '草稿已自动保存';
    });

    // 手动保存
    function saveDraft() {
      localStorage.setItem(STORAGE_KEY, contentEl.value);
      tipEl.innerText = '草稿手动保存成功';
    }

    // 清空草稿
    function clearDraft() {
      localStorage.removeItem(STORAGE_KEY);
      contentEl.value = '';
      tipEl.innerText = '草稿已清空';
    }

    // 进阶:带过期时间的本地存储(示例)
    function setStorageWithExpire(key, value, expireHours) {
      const data = {
        value: value,
        expire: Date.now() + expireHours * 3600 * 1000 // 过期时间戳
      };
      localStorage.setItem(key, JSON.stringify(data));
    }

    // 读取带过期的存储
    function getStorageWithExpire(key) {
      const data = JSON.parse(localStorage.getItem(key));
      if (!data) return null;
      // 过期则删除并返回null
      if (Date.now() > data.expire) {
        localStorage.removeItem(key);
        return null;
      }
      return data.value;
    }
  </script>
</body>
</html>

关键解析

localStorage 仅存字符串,存储对象需用 JSON.stringify(),读取用 JSON.parse(); 

实时保存:监听 input 事件,输入时自动保存,提升用户体验;

过期处理:自定义封装带过期时间的存储方法,解决 localStorage 无原生过期的问题。

5. Canvas 2D 绘图实战(基础可视化)

应用场景:开发简单图表、验证码、手绘板,替代图片资源,动态生成图形。

核心知识点:Canvas 上下文、路径绘制、样式设置、鼠标交互。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas 实战 - 简易手绘板</title>
  <style>
    canvas { border: 1px solid #ccc; cursor: crosshair; }
    .control { margin: 10px 0; }
    button { padding: 8px 15px; cursor: pointer; }
  </style>
</head>
<body>
  <div class="control">
    <button onclick="clearCanvas()">清空画布</button>
    <label>画笔颜色:</label>
    <input type="color" id="colorPicker" value="#000000">
  </div>
  <canvas id="drawCanvas" width="800" height="400"></canvas>

  <script>
    const canvas = document.getElementById('drawCanvas');
    const ctx = canvas.getContext('2d');
    const colorPicker = document.getElementById('colorPicker');
    let isDrawing = false; // 是否正在绘制

    // 开始绘制(鼠标按下)
    canvas.addEventListener('mousedown', function(e) {
      isDrawing = true;
      // 获取鼠标在画布内的坐标(修正画布偏移)
      const x = e.offsetX;
      const y = e.offsetY;
      ctx.beginPath(); // 开始新路径
      ctx.moveTo(x, y); // 移动到起始点
      ctx.lineWidth = 2; // 画笔宽度
      ctx.strokeStyle = colorPicker.value; // 画笔颜色
      ctx.lineCap = 'round'; // 线条端点圆润
    });

    // 绘制中(鼠标移动)
    canvas.addEventListener('mousemove', function(e) {
      if (!isDrawing) return;
      const x = e.offsetX;
      const y = e.offsetY;
      ctx.lineTo(x, y); // 绘制线条到当前点
      ctx.stroke(); // 描边(显示线条)
    });

    // 结束绘制(鼠标松开/离开)
    canvas.addEventListener('mouseup', () => isDrawing = false);
    canvas.addEventListener('mouseleave', () => isDrawing = false);

    // 清空画布
    function clearCanvas() {
      // 清空整个画布(从0,0到宽高)
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
  </script>
</body>
</html>

关键解析

offsetX/offsetY:获取鼠标相对于画布的坐标(而非页面),避免画布偏移导致坐标错误; 

lineCap='round':让画笔线条端点更圆润,提升手绘体验;

绘制逻辑:mousedown 开始路径 → mousemove 绘制线条 → mouseup 结束绘制。

6. HTML5 拖放(Drag & Drop)实战

应用场景:开发「拖拽排序」「文件上传」「组件拖拽布局」,原生实现无需第三方库。

核心知识点:draggable 属性、dragstart/dragover/drop 事件、数据传输 dataTransfer。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML5 拖放实战 - 拖拽排序</title>
  <style>
    .container { display: flex; gap: 10px; margin: 20px; }
    .drag-item { 
      width: 100px; height: 100px; 
      background: #007bff; color: #fff;
      display: flex; align-items: center; justify-content: center;
      cursor: move; user-select: none; /* 禁止文字选中 */
    }
    .drop-area { 
      flex: 1; min-height: 300px; 
      border: 2px dashed #ccc; padding: 10px;
      display: flex; flex-wrap: wrap; gap: 10px;
    }
    .drop-area.active { border-color: #007bff; }
  </style>
</head>
<body>
  <div class="container">
    <!-- 可拖拽元素 -->
    <div>
      <div class="drag-item" draggable="true" data-id="1">元素1</div>
      <div class="drag-item" draggable="true" data-id="2">元素2</div>
      <div class="drag-item" draggable="true" data-id="3">元素3</div>
    </div>

    <!-- 放置区域 -->
    <div class="drop-area" id="dropArea"></div>
  </div>

  <script>
    const dragItems = document.querySelectorAll('.drag-item');
    const dropArea = document.getElementById('dropArea');

    // 1. 拖拽开始:设置传输数据
    dragItems.forEach(item => {
      item.addEventListener('dragstart', function(e) {
        // 设置拖拽数据(id)
        e.dataTransfer.setData('text/plain', this.dataset.id);
        // 设置拖拽效果(视觉提示)
        e.dataTransfer.effectAllowed = 'move';
        // 高亮拖拽元素(可选)
        this.style.opacity = '0.5';
      });

      // 拖拽结束:恢复样式
      item.addEventListener('dragend', function() {
        this.style.opacity = '1';
      });
    });

    // 2. 拖拽经过:必须阻止默认行为,否则无法触发drop
    dropArea.addEventListener('dragover', function(e) {
      e.preventDefault();
      this.classList.add('active');
      e.dataTransfer.dropEffect = 'move'; // 设置放置效果
    });

    // 拖拽离开:移除高亮
    dropArea.addEventListener('dragleave', function() {
      this.classList.remove('active');
    });

    // 3. 放置元素:处理逻辑
    dropArea.addEventListener('drop', function(e) {
      e.preventDefault();
      this.classList.remove('active');
      // 获取拖拽的元素ID
      const id = e.dataTransfer.getData('text/plain');
      // 找到拖拽的元素
      const dragItem = document.querySelector(`[data-id="${id}"]`);
      // 克隆元素并添加到放置区域(也可直接移动)
      const cloneItem = dragItem.cloneNode(true);
      cloneItem.draggable = true; // 克隆后需重新设置draggable
      this.appendChild(cloneItem);
    });
  </script>
</body>
</html>

关键解析

dragover 必须阻止默认行为(e.preventDefault()),否则 drop 事件不会触发; 

dataTransfer:用于传输拖拽数据(如元素 ID),仅支持字符串类型;

dragend:恢复拖拽元素样式,避免拖拽后样式异常。

7. Web Worker 实战(避免主线程阻塞)

应用场景:处理大数据计算、复杂逻辑(如数据解析、加密),避免页面卡顿。 

核心知识点:Web Worker 线程创建、消息通信、错误处理、线程终止。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Web Worker 实战 - 大数据计算</title>
  <style>
    .demo { max-width: 600px; margin: 20px auto; }
    #result { margin: 20px 0; padding: 10px; border: 1px solid #eee; }
    button { padding: 10px 20px; cursor: pointer; }
  </style>
</head>
<body>
  <div class="demo">
    <h3>Web Worker 大数据计算(不阻塞页面)</h3>
    <button onclick="startCalculation()">开始计算(1000万次循环)</button>
    <button onclick="stopWorker()" disabled id="stopBtn">终止计算</button>
    <div id="result">计算结果:等待计算...</div>
    <!-- 测试页面是否卡顿:可拖动的滑块 -->
    <input type="range" style="width: 100%; margin-top: 20px;" value="50">
  </div>

  <script>
    let worker; // 保存Worker实例
    const resultEl = document.getElementById('result');
    const stopBtn = document.getElementById('stopBtn');

    // 开始计算
    function startCalculation() {
      // 1. 创建Web Worker(单独的JS文件)
      worker = new Worker('calculation-worker.js');
      stopBtn.disabled = false;
      resultEl.innerText = '计算中...';

      // 2. 向Worker发送数据
      worker.postMessage({ count: 10000000 });

      // 3. 接收Worker返回的结果
      worker.onmessage = function(e) {
        resultEl.innerText = `计算结果:${e.data}(耗时:${e.data.cost}ms)`;
        stopBtn.disabled = true;
        worker.terminate(); // 计算完成后终止Worker
        worker = null;
      };

      // 4. 监听Worker错误
      worker.onerror = function(error) {
        resultEl.innerText = `计算出错:${error.message}(行:${error.lineno})`;
        stopBtn.disabled = true;
        worker.terminate();
        worker = null;
      };
    }

    // 终止计算
    function stopWorker() {
      if (worker) {
        worker.terminate();
        worker = null;
        resultEl.innerText = '计算已终止';
        stopBtn.disabled = true;
      }
    }
  </script>
</body>
</html>

新建 calculation-worker.js 文件(与 HTML 同目录):

// Worker线程代码(无法访问DOM、window,仅能通过postMessage通信)
self.onmessage = function(e) {
  const start = Date.now();
  const count = e.data.count;
  let sum = 0;

  // 模拟大数据计算(1000万次循环)
  for (let i = 0; i < count; i++) {
    sum += Math.sqrt(i) * Math.random();
  }

  const cost = Date.now() - start;
  // 向主线程返回结果
  self.postMessage({ sum: sum.toFixed(2), cost: cost });
};

关键解析

 Web Worker 无法访问 DOM、window、document,仅能通过 postMessage 与主线程通信;

 计算完成 / 出错后需调用 terminate() 终止 Worker,避免内存泄漏;

 优势:计算时页面滑块仍可拖动,证明主线程未阻塞。

8. Fetch API 实战(新一代网络请求)

应用场景

替代 AJAX/XMLHttpRequest,开发接口请求、文件上传,支持 Promise 和异步编程。

核心知识点

Fetch 基本用法、请求头设置、POST 请求、文件上传、响应处理、错误捕获。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Fetch API 实战</title>
  <style>
    .demo { max-width: 600px; margin: 20px auto; }
    #response { margin: 20px 0; padding: 10px; border: 1px solid #eee; white-space: pre-wrap; }
    button { margin-right: 10px; padding: 8px 15px; cursor: pointer; }
  </style>
</head>
<body>
  <div class="demo">
    <h3>Fetch API 实战</h3>
    <button onclick="getApiData()">GET 请求(获取数据)</button>
    <button onclick="postApiData()">POST 请求(提交数据)</button>
    <button onclick="uploadFile()">上传文件</button>
    <div id="response">响应结果:等待请求...</div>
    <input type="file" id="fileInput" style="margin-top: 10px;">
  </div>

  <script>
    const responseEl = document.getElementById('response');
    const fileInput = document.getElementById('fileInput');

    // 封装通用Fetch请求(简化代码)
    async function request(url, options = {}) {
      try {
        // 默认配置
        const defaultOptions = {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json' // 默认JSON格式
          },
          credentials: 'same-origin' // 携带同域Cookie
        };
        const config = { ...defaultOptions, ...options };

        // 发送请求
        const response = await fetch(url, config);

        // 检查响应状态(Fetch仅在网络错误时reject,状态码非200需手动处理)
        if (!response.ok) {
          throw new Error(`请求失败:${response.status} ${response.statusText}`);
        }

        // 解析响应(根据返回格式选择json/text/blob等)
        const data = await response.json();
        return data;
      } catch (error) {
        responseEl.innerText = `请求错误:${error.message}`;
        throw error; // 抛出错误供上层处理
      }
    }

    // 1. GET请求(示例:获取公共API数据)
    async function getApiData() {
      responseEl.innerText = '请求中...';
      try {
        const data = await request('https://jsonplaceholder.typicode.com/posts/1');
        responseEl.innerText = JSON.stringify(data, null, 2);
      } catch (error) {
        console.error('GET请求失败:', error);
      }
    }

    // 2. POST请求(提交JSON数据)
    async function postApiData() {
      responseEl.innerText = '请求中...';
      try {
        const data = await request('https://jsonplaceholder.typicode.com/posts', {
          method: 'POST',
          body: JSON.stringify({
            title: 'HTML5 Fetch 实战',
            body: '这是POST请求测试',
            userId: 1
          })
        });
        responseEl.innerText = JSON.stringify(data, null, 2);
      } catch (error) {
        console.error('POST请求失败:', error);
      }
    }

    // 3. 文件上传(FormData格式)
    async function uploadFile() {
      const file = fileInput.files[0];
      if (!file) {
        responseEl.innerText = '请先选择文件';
        return;
      }

      responseEl.innerText = '上传中...';
      try {
        // 构建FormData(文件上传专用)
        const formData = new FormData();
        formData.append('file', file);
        formData.append('name', '测试文件');

        // 发送上传请求(注意:Content-Type需由浏览器自动设置为multipart/form-data)
        const data = await request('https://jsonplaceholder.typicode.com/posts', {
          method: 'POST',
          body: formData,
          headers: {} // 清空默认的Content-Type,避免冲突
        });
        responseEl.innerText = `上传成功:${JSON.stringify(data, null, 2)}`;
      } catch (error) {
        console.error('文件上传失败:', error);
      }
    }
  </script>
</body>
</html>

关键解析

Fetch 仅在「网络错误」时 reject,状态码 404/500 等需通过 response.ok 手动判断;

文件上传需用 FormData,且需清空 Content-Type,由浏览器自动设置(避免格式错误);

封装通用 request 函数:减少重复代码,统一处理错误和配置。

9. Service Worker 实战(离线缓存)

应用场景:开发 PWA 应用、实现页面离线访问、缓存静态资源,提升页面加载速度。

核心知识点:Service Worker 注册、安装、激活、缓存策略、拦截请求。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Service Worker 实战 - 离线缓存</title>
  <style>
    .demo { max-width: 600px; margin: 20px auto; text-align: center; }
    #status { margin: 20px 0; padding: 10px; border: 1px solid #eee; }
  </style>
</head>
<body>
  <div class="demo">
    <h3>Service Worker 离线缓存演示</h3>
    <p>刷新页面后断网,仍可访问页面和缓存的资源</p>
    <div id="status">Service Worker 状态:未注册</div>
    <img src="logo.png" alt="测试图片" width="200">
  </div>

  <script>
    const statusEl = document.getElementById('status');

    // 1. 检查浏览器是否支持Service Worker
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', async () => {
        try {
          // 2. 注册Service Worker(需在HTTPS/localhost环境下)
          const registration = await navigator.serviceWorker.register('/sw.js');
          
          if (registration.installing) {
            statusEl.innerText = 'Service Worker 正在安装...';
          } else if (registration.waiting) {
            statusEl.innerText = 'Service Worker 已安装,等待激活...';
          } else if (registration.active) {
            statusEl.innerText = 'Service Worker 已激活,支持离线访问!';
          }
        } catch (error) {
          statusEl.innerText = `Service Worker 注册失败:${error.message}`;
        }
      });
    } else {
      statusEl.innerText = '您的浏览器不支持 Service Worker';
    }
  </script>
</body>
</html>

新建 sw.js 文件(根目录):

// 缓存名称(更新缓存时修改名称)
const CACHE_NAME = 'html5-demo-v1';
// 需要缓存的资源列表
const CACHE_ASSETS = [
  '/', // 首页
  '/index.html', // HTML文件
  '/logo.png' // 测试图片(替换为实际图片路径)
];

// 1. 安装阶段:缓存静态资源
self.addEventListener('install', function(e) {
  // 等待缓存完成后激活
  e.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('缓存已打开,开始缓存资源');
        // 批量缓存资源(Promise.all)
        return cache.addAll(CACHE_ASSETS);
      })
      .then(function() {
        // 跳过等待,直接激活(可选)
        return self.skipWaiting();
      })
  );
});

// 2. 激活阶段:清理旧缓存
self.addEventListener('activate', function(e) {
  e.waitUntil(
    caches.keys().then(function(cacheNames) {
      // 遍历所有缓存名称,删除旧缓存
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheName !== CACHE_NAME) {
            console.log('删除旧缓存:', cacheName);
            return caches.delete(cacheName);
          }
        })
      );
    }).then(function() {
      // 控制所有打开的页面(可选)
      return self.clients.claim();
    })
  );
});

// 3. 拦截请求:优先从缓存读取,缓存无则请求网络
self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.match(e.request)
      .then(function(response) {
        // 缓存中有则返回,无则请求网络
        return response || fetch(e.request).catch(function() {
          // 网络失败且无缓存时,返回兜底页面(可选)
          return caches.match('/');
        });
      })
  );
});

关键解析

Service Worker 需运行在 HTTPS 或 localhost 环境下,本地开发可用 localhost; 

缓存名称(CACHE_NAME):更新缓存时修改名称,触发重新安装;

缓存策略:示例为「缓存优先」,也可根据需求实现「网络优先」「缓存 + 网络」等策略。

10. HTML5 地理位置(Geolocation)+ 百度地图实战

应用场景:开发「定位服务」「附近商家」「地图应用」,结合第三方地图 API 实现可视化。

核心知识点:Geolocation 获取位置、百度地图 API 调用、坐标转换。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML5 地理位置 + 百度地图实战</title>
  <style>
    #map { width: 100%; height: 400px; margin: 20px 0; border: 1px solid #eee; }
    .demo { max-width: 800px; margin: 0 auto; padding: 20px; }
  </style>
  <!-- 引入百度地图API(替换为自己的AK) -->
  <script src="https://api.map.baidu.com/api?v=3.0&ak=你的百度地图AK"></script>
</head>
<body>
  <div class="demo">
    <h3>HTML5 定位 + 百度地图</h3>
    <button onclick="getLocation()">获取我的位置</button>
    <p id="locationInfo">位置信息:未定位</p>
    <div id="map"></div>
  </div>

  <script>
    const locationInfoEl = document.getElementById('locationInfo');
    let map; // 百度地图实例

    // 初始化百度地图
    function initMap(lng, lat) {
      // 创建地图实例
      map = new BMapGL.Map("map");
      // 设置中心点坐标(HTML5获取的是WGS84坐标,需转换为百度坐标)
      const point = new BMapGL.Point(lng, lat);
      // 初始化地图,设置中心点坐标和地图级别
      map.centerAndZoom(point, 15);
      // 开启鼠标滚轮缩放
      map.enableScrollWheelZoom(true);
      // 添加标记
      const marker = new BMapGL.Marker(point);
      map.addOverlay(marker);
      // 添加信息窗口
      const infoWindow = new BMapGL.InfoWindow("我的位置");
      marker.addEventListener("click", function(){
        map.openInfoWindow(infoWindow, point);
      });
    }

    // 获取地理位置
    function getLocation() {
      // 检查浏览器是否支持Geolocation
      if (!navigator.geolocation) {
        locationInfoEl.innerText = '您的浏览器不支持地理位置定位';
        return;
      }

      locationInfoEl.innerText = '正在定位...';

      // 1. 获取当前位置(高精度)
      navigator.geolocation.getCurrentPosition(
        // 成功回调
        function(position) {
          const lng = position.coords.longitude; // 经度
          const lat = position.coords.latitude; // 纬度
          const accuracy = position.coords.accuracy; // 精度(米)

          locationInfoEl.innerText = `位置信息:经度${lng.toFixed(6)},纬度${lat.toFixed(6)},精度${accuracy}米`;

          // 2. 转换坐标(WGS84 → 百度坐标,需后端接口,此处简化直接使用)
          // 注:实际项目需调用百度地图坐标转换API,避免偏移
          initMap(lng, lat);
        },
        // 失败回调
        function(error) {
          let errorMsg = '';
          switch(error.code) {
            case error.PERMISSION_DENIED:
              errorMsg = '用户拒绝定位权限';
              break;
            case error.POSITION_UNAVAILABLE:
              errorMsg = '位置信息不可用';
              break;
            case error.TIMEOUT:
              errorMsg = '定位请求超时';
              break;
            case error.UNKNOWN_ERROR:
              errorMsg = '未知错误';
              break;
          }
          locationInfoEl.innerText = `定位失败:${errorMsg}`;
        },
        // 配置项
        {
          enableHighAccuracy: true, // 高精度定位
          timeout: 10000, // 超时时间(10秒)
          maximumAge: 30000 // 缓存时间(30秒)
        }
      );
    }
  </script>
</body>
</html>

关键解析: 

百度地图 AK 需要在「百度地图开放平台」申请(免费);

HTML5 获取的是 WGS84 坐标,百度地图使用 BD09 坐标,需调用坐标转换 API 避免偏移; 

定位权限:需用户授权,失败时需处理多种错误场景(如用户拒绝、超时)。

总结 

入门核心:语义化标签、新表单控件、多媒体标签是 HTML5 基础,需掌握「结构语义化」和「原生控件减少 JS 开发」;

进阶重点:localStorage 数据持久化、Canvas 绘图、拖放 API 是前端高频功能,需理解「事件驱动」和「数据交互」逻辑;

高级应用:Web Worker 解决主线程阻塞、Fetch 替代 AJAX、Service Worker 实现离线缓存、Geolocation 结合地图 API,需掌握「异步编程」和「跨线程通信」,同时注意浏览器兼容性和权限问题。