HTML5 是超文本标记语言(HTML)的第五个版本,发布于2014年,新增了对多媒体、图形、离线存储等功能的原生支持,同时更注重语义化和跨平台兼容性。它是用于构建和展示网页的标准技术。HTML5 引入了许多新特性和元素,以增强网页的结构和功能。以下是一些主要内容:
1.语义化标签(新增结构化标签替代传统的<div>
布局)
-
<header>
:页眉或内容头部 -
<nav>
:导航栏 -
<main>
:页面主要内容 -
<section>
:内容区块 -
<article>
:独立文章内容 -
<aside>
:侧边栏或附加内容 -
<footer>
:页脚
1.1语义化标签的核心优势
- 增强可访问性:屏幕阅读器等辅助技术能准确识别标签含义(如
<nav>
表示导航),提升残障用户的浏览体验。 - SEO 优化:搜索引擎更易解析内容结构,识别关键内容(如
<article>
内的文章),提高页面排名。 - 代码可读性与维护性:标签自解释性强(如
<header>
、<footer>
),减少对类名的依赖,便于团队协作和后期维护。 - 浏览器优化:部分标签(如
<main>
)可能触发浏览器的默认优化行为,提升渲染效率。
2.多媒体支持:HTML5 为音频和视频提供了原生支持,添加了 <audio>
和 <video>
元素,允许在网页中轻松嵌入多媒体内容,而不需要第三方插件。
2.1.video标签
直接使用 src属性时,只能加载单个视频源。推荐通过 <source>标签支持多格式兼容,解决浏览器兼容性问题 <video src="video.mp4" controls> 您的浏览器不支持 HTML5 视频。 </video> <video controls> <source src="video.mp4" type="video/mp4"> <source src="video.webm" type="video/webm"> </video>
controls
:显示浏览器默认播放控件(播放/暂停、进度条、音量等)。
autoplay
:自动播放(受浏览器策略限制,通常需静音)。
muted
:默认静音。
loop
:循环播放。
poster
:视频封面图(未播放时显示的图像)。
preload
:预加载策略(auto|metadata|none
)。
width
/height
:设置视频显示尺寸。移动端优化
延迟加载:使用
preload="none"
减少首屏加载时间。触控事件:处理
touchstart
事件以绕过自动播放限制。
2.2.audio标签
基础用法 <audio src="audio.mp3" controls> 您的浏览器不支持 HTML5 音频。 </audio>
多格式兼容 <audio controls> <source src="audio.mp3" type="audio/mpeg"> <source src="audio.ogg" type="audio/ogg"> 您的浏览器不支持音频播放。 </audio>
controls
:显示播放控件。
autoplay
:自动播放(移动端通常禁用)。
loop
:循环播放。
preload
:预加载策略(类似<video>
)。
3.1.canvas:<canvas>
元素是前端开发中实现动态图形和复杂可视化的核心工具。
1. 创建画布
<canvas id="myCanvas" width="800" height="600"> 您的浏览器不支持 canvas,请升级或更换浏览器。 </canvas>
width
和height
:必须通过属性(而非 CSS)设置画布分辨率,避免拉伸失真。回退内容:在不支持
canvas
的浏览器中显示替代内容。2. 获取绘图上下文
const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); // 2D 上下文 // const gl = canvas.getContext('webgl'); // WebGL 上下文(3D)
2d
:用于 2D 绘图(路径、形状、文本、图像操作)。
webgl
:用于 3D 渲染(基于 OpenGL ES)。2D 绘图 API
矩形:
ctx.fillStyle = 'blue'; // 填充颜色 ctx.fillRect(10, 10, 100, 50); // 填充矩形(x, y, width, height) ctx.strokeStyle = 'red'; // 描边颜色 ctx.strokeRect(50, 50, 80, 30); // 描边矩形
路径:
ctx.beginPath(); ctx.moveTo(100, 100); // 起点 ctx.lineTo(200, 150); // 直线 ctx.arc(250, 250, 30, 0, Math.PI * 2); // 圆 ctx.closePath(); // 闭合路径 ctx.fill(); // 填充路径 ctx.stroke(); // 描边路径
颜色与渐变:
// 线性渐变 const gradient = ctx.createLinearGradient(0, 0, 200, 0); gradient.addColorStop(0, 'red'); gradient.addColorStop(1, 'blue'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, 200, 100); // 径向渐变 const radialGrad = ctx.createRadialGradient(150, 150, 10, 150, 150, 50); radialGrad.addColorStop(0, 'white'); radialGrad.addColorStop(1, 'black');
阴影:
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; ctx.shadowBlur = 10; ctx.shadowOffsetX = 5; ctx.shadowOffsetY = 5;
. 文本绘制
ctx.font = '20px Arial'; // 字体设置 ctx.fillStyle = 'green'; ctx.fillText('Hello Canvas', 50, 50); // 填充文本 ctx.strokeText('Hello Canvas', 50, 80); // 描边文本
. 图像操作
const img = new Image(); img.src = 'image.jpg'; img.onload = () => { // 绘制图像(支持裁剪与缩放) ctx.drawImage(img, 0, 0, 200, 100); };
3.2.svg:矢量图形,基于数学公式定义图形,无限缩放不失真,适合 Retina 屏和高分辨率设备。文件体积小(相比位图),尤其适合简单图形(如图标、LOGO)。
XML 语法
直接嵌入 HTML 或作为独立文件(
.svg
)引用。支持 CSS 样式、JavaScript 操作,与 DOM 无缝集成。
DOM 可访问性
每个图形元素(如
<path>
,<circle>
)均为 DOM 节点,支持:
事件绑定(点击、悬停等)。
动态修改属性(如
fill
,transform
)。CSS 动画/过渡。
<svg width="200" height="200" viewBox="0 0 100 100">
<!-- 矩形 -->
<rect x="10" y="10" width="50" height="30" fill="#f00" stroke="#000" stroke-width="2" />
<!-- 圆形 -->
<circle cx="70" cy="50" r="20" fill="blue" opacity="0.8" />
<!-- 路径(贝塞尔曲线) -->
<path d="M10 80 Q 50 10, 90 80 T 150 80" stroke="green" fill="none" />
</svg>
4表单增强:大大增强了表单的功能和交互性。
<input type="email">
: 用于输入电子邮件地址的字段,浏览器会对输入进行简单的格式验证。
<input type="url">
: 用于输入网址的字段,浏览器会进行格式验证。
<input type="tel">
: 用于输入电话号码的字段,虽然没有格式验证,但是在移动设备上会显示数字键盘。
<input type="number">
: 用于输入数字的字段,提供上下箭头来增减数字值。
<input type="range">
: 创建一个滑动条,用于选择数值范围。
<input type="date">
: 用于输入日期, 带有一个日期选择器。
<input type="time">
: 用于输入时间, 带有一个时间选择器。
<input type="datetime-local">
: 用于输入本地日期和时间, 带有一个选择器。
<input type="month">
: 用于选择月份和年份。
<input type="week">
: 用于选择年份中的周。
<input type="color">
: 用于选择颜色的字段, 带有颜色选择器。
5.存储技术:
5.1.本地存储 (localStorage
)
持久化存储(浏览器关闭后数据保留)
- 存储容量较大(一般为 5-10MB)
- 仅存储字符串数据
- 同源策略限制(数据仅在同源页面共享)
使用场景:用户偏好设置(如主题、字体大小),离线数据缓存(如历史搜索记录),静态资源缓存(如CSS、JS文件)
// 存储数据 localStorage.setItem('key', 'value')
// 获取数据 localStorage.getItem('key')
// 删除数据 localStorage.removeItem('key')
// 清空所有数据 localStorage.clear()
5.2.临时存储(sessionStorage)
会话级存储(标签页关闭后数据清除)
容量与
localStorage
相同。使用场景:临时表单数据(如多步骤表单的中间状态),单页应用的临时状态管理(如购物车内容
// 存储数据 sessionStorage.setItem('key', 'value')
// 获取数据 sessionStorage.getItem('key')
// 删除数据 sessionStorage.removeItem('key')
// 清空所有数据 sessionStorage.clear()
5.3.IndexedDB(取代了已废弃的Web SQL)
- 支持结构化数据存储,容量更大(通常250MB以上)
- 支持事务、索引查询和异步操作。
使用场景:
离线应用(如邮件客户端、文档编辑器)
复杂数据查询(如大型电商网站的商品数据)
需要高性能存储的场景(如实时数据分析)
// 打开数据库
const request = indexedDB.open('myDatabase', 1)
request.onerror = (event) => {
console.error('数据库打开失败')
}
request.onsuccess = (event) => {
const db = event.target.result
}
// 创建对象仓库
request.onupgradeneeded = (event) => {
const db = event.target.result
const objectStore = db.createObjectStore('users', { keyPath: 'id' })
objectStore.createIndex('name', 'name', { unique: false })
}
// 添加数据
function addData(db, user) {
const transaction = db.transaction(['users'], 'readwrite')
const objectStore = transaction.objectStore('users')
const request = objectStore.add(user)
}
// 查询数据
function getData(db, id) {
const transaction = db.transaction(['users'])
const objectStore = transaction.objectStore('users')
const request = objectStore.get(id)
request.onsuccess = (event) => {
console.log('查询结果:', event.target.result)
}
}
5.4.File API
允许通过JavaScript访问本地文件系统
支持文件读取、预览和分段上传。
- 存储容量大(无固定上限)
使用场景:文件上传功能(如用户头像上传),本地文件处理(如图片裁剪、PDF预览)
// 基础文件上传:
<input type="file" id="fileInput" multiple>
const fileInput = document.getElementById('fileInput')
fileInput.addEventListener('change', (e) => {
const files = e.target.files
for(let file of files) {
console.log('文件名:', file.name)
console.log('大小:', file.size)
console.log('类型:', file.type)
}
})
// 图片预览:
function previewImage(file) {
const reader = new FileReader()
reader.onload = (e) => {
const img = document.createElement('img')
img.src = e.target.result
document.body.appendChild(img)
}
reader.readAsDataURL(file)
}
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0]
if(file.type.startsWith('image/')) {
previewImage(file)
}
})
// 拖拽上传:
<div id="dropZone">拖拽文件到这里</div>
const dropZone = document.getElementById('dropZone')
dropZone.addEventListener('dragover', (e) => {
e.preventDefault()
})
dropZone.addEventListener('drop', (e) => {
e.preventDefault()
const files = e.dataTransfer.files
for(let file of files) {
console.log('接收到文件:', file.name)
}
})
// 文件切片上传:
function sliceFile(file, chunkSize = 1024 * 1024) {
const chunks = []
let start = 0
while(start < file.size) {
const chunk = file.slice(start, start + chunkSize)
chunks.push(chunk)
start += chunkSize
}
return chunks
}
// 使用示例
const chunks = sliceFile(file)
chunks.forEach((chunk, index) => {
const formData = new FormData()
formData.append('chunk', chunk)
formData.append('index', index)
// 上传chunk
})
6.Geolocation API 是 HTML5 提供的获取用户地理位置的 API,可以获取经纬度、海拔、精确度等信息。(/ˌdʒiːəʊləʊˈkeɪʃ(ə)n/)
获取当前位置:
// 基本语法
navigator.geolocation.getCurrentPosition(successCallback, errorCallback, options)
// 实际应用
navigator.geolocation.getCurrentPosition(
// 成功回调
(position) => {
const latitude = position.coords.latitude // 纬度
const longitude = position.coords.longitude // 经度
const accuracy = position.coords.accuracy // 精确度
const altitude = position.coords.altitude // 海拔
const timestamp = position.timestamp // 获取时间戳
},
// 错误回调
(error) => {
switch(error.code) {
case error.PERMISSION_DENIED:
console.error("用户拒绝定位请求")
break
case error.POSITION_UNAVAILABLE:
console.error("位置信息不可用")
break
case error.TIMEOUT:
console.error("获取用户位置超时")
break
}
},
// 配置选项
{
enableHighAccuracy: true, // 是否高精度
timeout: 5000, // 超时时间
maximumAge: 0 // 缓存时间
}
)
// 开始监听
const watchId = navigator.geolocation.watchPosition(
(position) => {
console.log('位置更新:', position.coords)
},
(error) => {
console.error('监听错误:', error)
}
)
// 停止监听
navigator.geolocation.clearWatch(watchId)
7.应用缓存:传统AppCache(/kæʃ/) 已被废弃,当前推荐Service Worker:
// main.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
try {
const registration = await navigator.serviceWorker.register('/sw.js', {
scope: '/' // 作用域
})
console.log('SW 注册成功,作用域:', registration.scope)
} catch (error) {
console.error('SW 注册失败:', error)
}
})
}
// sw.js
const CACHE_NAME = 'app-v1'
const CACHE_URLS = [
'/',
'/index.html',
'/styles/main.css',
'/scripts/app.js',
'/images/logo.png'
]
// 安装事件
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(CACHE_URLS))
)
})
// 激活事件
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(name => name !== CACHE_NAME)
.map(name => caches.delete(name))
)
})
)
})
// 请求拦截
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
)
})
// 缓存优先(Cache First):
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// 命中缓存
if (response) {
return response
}
// 未命中缓存,发起网络请求
return fetch(event.request).then(
response => {
// 检查响应
if (!response || response.status !== 200) {
return response
}
// 复制响应
const responseToCache = response.clone()
// 存入缓存
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache)
})
return response
}
)
})
)
})
// 网络优先(Network First):
self.addEventListener('fetch', event => {
event.respondWith(
fetch(event.request)
.then(response => {
// 请求成功,更新缓存
const responseToCache = response.clone()
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache)
})
return response
})
.catch(() => {
// 请求失败,使用缓存
return caches.match(event.request)
})
)
})
// Stale While Revalidate:
self.addEventListener('fetch', event => {
event.respondWith(
caches.open(CACHE_NAME).then(cache => {
return cache.match(event.request).then(response => {
const fetchPromise = fetch(event.request).then(networkResponse => {
cache.put(event.request, networkResponse.clone())
return networkResponse
})
return response || fetchPromise
})
})
)
})
// 在页面中发送消息
navigator.serviceWorker.controller.postMessage({
type: 'CACHE_NEW_VERSION',
payload: { version: 'v2' }
})
// 在 Service Worker 中接收消息
self.addEventListener('message', event => {
if (event.data.type === 'CACHE_NEW_VERSION') {
// 处理消息
console.log('新版本:', event.data.payload.version)
}
})
// 版本控制:
const VERSION = 'v1.0.0'
const CACHE_NAME = `app-${VERSION}`
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(name => name.startsWith('app-') && name !== CACHE_NAME)
.map(name => caches.delete(name))
)
})
)
})
8.网络通信:双向实时通信的首选方案WebSockets
class WebSocketClient {
constructor(url) {
this.url = url
this.ws = null
this.reconnectAttempts = 0
this.maxReconnectAttempts = 5
}
connect() {
this.ws = new WebSocket(this.url)
this.ws.onopen = () => {
console.log('连接成功')
this.reconnectAttempts = 0
}
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data)
console.log('收到消息:', data)
}
this.ws.onclose = () => {
console.log('连接关闭')
this.reconnect()
}
this.ws.onerror = (error) => {
console.error('WebSocket错误:', error)
}
}
send(data) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data))
}
}
reconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++
setTimeout(() => {
console.log(`尝试重连 ${this.reconnectAttempts}`)
this.connect()
}, 1000 * this.reconnectAttempts)
}
}
close() {
if (this.ws) {
this.ws.close()
}
}
}
// 使用示例
const ws = new WebSocketClient('ws://example.com/socket')
ws.connect()
ws.send({ type: 'message', content: 'Hello' })
// 实时聊天应用:
class ChatApp {
constructor() {
this.ws = new WebSocketClient('ws://chat.example.com')
this.http = new HttpClient('https://api.example.com')
}
async init() {
// 获取历史消息
const history = await this.http.get('/chat/history')
this.displayMessages(history)
// 建立WebSocket连接
this.ws.connect()
this.ws.onmessage = this.handleNewMessage.bind(this)
}
async sendMessage(message) {
// 发送到WebSocket
this.ws.send({
type: 'chat',
content: message
})
// 保存到服务器
await this.http.post('/chat/messages', {
content: message
})
}
handleNewMessage(message) {
this.displayMessage(message)
}
displayMessage(message) {
// 显示消息的UI逻辑
}
}
9.设备访问
class DeviceManager {
constructor() {
this.location = new LocationService()
this.media = new MediaDeviceService()
this.sensor = new DeviceSensorService()
this.battery = new BatteryService()
this.vibration = new VibrationService()
this.light = new AmbientLightService()
}
// 设备信息收集
async collectDeviceInfo() {
const info = {
timestamp: new Date().toISOString()
}
try {
// 获取位置
info.location = await this.location.getCurrentPosition()
// 获取电池状态
if (this.battery.supported) {
info.battery = await this.battery.getBatteryInfo()
}
// 获取媒体设备
info.devices = await this.media.getDevices()
return info
} catch (error) {
console.error('设备信息收集失败:', error)
throw error
}
}
// 设备监控
startMonitoring(callbacks = {}) {
// 监听位置变化
const watchId = this.location.watchPosition(callbacks.onLocation)
// 监听设备方向
this.sensor.listenOrientation(callbacks.onOrientation)
// 监听电池状态
this.battery.watchBattery({
onChargingChange: callbacks.onBatteryCharging,
onLevelChange: callbacks.onBatteryLevel
})
// 监听环境光
if (this.light.supported) {
this.light.watchLight(callbacks.onLightChange)
}
return watchId
}
}
// 使用示例
const deviceManager = new DeviceManager()
// 收集设备信息
deviceManager.collectDeviceInfo()
.then(info => console.log('设备信息:', info))
.catch(error => console.error('错误:', error))
// 开始监控
deviceManager.startMonitoring({
onLocation: (pos) => console.log('位置更新:', pos),
onOrientation: (orient) => console.log('方向更新:', orient),
onBatteryLevel: (level) => console.log('电量更新:', level),
onLightChange: (lux) => console.log('光照度更新:', lux)
})