HTML5 新特性
HTML5 常用新特性及使用示例
问题
列举 HTML5 的主要新特性,包括语义化标签、Video/Audio、Canvas、LocalStorage、Drag API、Web Worker。
解答
1. 语义化标签
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>语义化标签示例</title>
</head>
<body>
<!-- 页面头部 -->
<header>
<nav>
<ul>
<li><a href="/">首页</a></li>
<li><a href="/about">关于</a></li>
</ul>
</nav>
</header>
<!-- 主要内容 -->
<main>
<article>
<header>
<h1>文章标题</h1>
<time datetime="2024-01-01">2024年1月1日</time>
</header>
<section>
<p>文章内容...</p>
</section>
<footer>
<p>作者:张三</p>
</footer>
</article>
<!-- 侧边栏 -->
<aside>
<h2>相关推荐</h2>
</aside>
</main>
<!-- 页面底部 -->
<footer>
<p>© 2024</p>
</footer>
</body>
</html>
常用语义化标签:
| 标签 | 用途 |
|---|---|
<header> | 页面或区块的头部 |
<nav> | 导航链接 |
<main> | 页面主要内容 |
<article> | 独立的文章内容 |
<section> | 文档中的节 |
<aside> | 侧边栏内容 |
<footer> | 页面或区块的底部 |
<figure> | 图片、图表等 |
<figcaption> | figure 的标题 |
<time> | 日期时间 |
<mark> | 高亮文本 |
2. Video/Audio
<!-- 视频播放 -->
<video
id="myVideo"
width="640"
height="360"
controls
poster="cover.jpg"
>
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
您的浏览器不支持视频播放
</video>
<!-- 音频播放 -->
<audio id="myAudio" controls>
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
您的浏览器不支持音频播放
</audio>
<script>
const video = document.getElementById('myVideo')
// 播放控制
video.play()
video.pause()
// 常用属性
console.log(video.currentTime) // 当前播放时间
console.log(video.duration) // 总时长
console.log(video.paused) // 是否暂停
console.log(video.volume) // 音量 0-1
// 常用事件
video.addEventListener('play', () => console.log('开始播放'))
video.addEventListener('pause', () => console.log('暂停'))
video.addEventListener('ended', () => console.log('播放结束'))
video.addEventListener('timeupdate', () => {
console.log('播放进度:', video.currentTime)
})
</script>
3. Canvas
<canvas id="myCanvas" width="400" height="300"></canvas>
<script>
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')
// 绘制矩形
ctx.fillStyle = '#3498db'
ctx.fillRect(10, 10, 100, 80)
// 绘制边框矩形
ctx.strokeStyle = '#e74c3c'
ctx.lineWidth = 3
ctx.strokeRect(130, 10, 100, 80)
// 绘制圆形
ctx.beginPath()
ctx.arc(300, 50, 40, 0, Math.PI * 2)
ctx.fillStyle = '#2ecc71'
ctx.fill()
// 绘制线条
ctx.beginPath()
ctx.moveTo(10, 120)
ctx.lineTo(100, 180)
ctx.lineTo(200, 120)
ctx.strokeStyle = '#9b59b6'
ctx.lineWidth = 2
ctx.stroke()
// 绘制文字
ctx.font = '24px Arial'
ctx.fillStyle = '#333'
ctx.fillText('Hello Canvas', 10, 230)
// 绘制图片
const img = new Image()
img.onload = () => {
ctx.drawImage(img, 200, 150, 100, 100)
}
img.src = 'image.png'
// 导出为图片
const dataURL = canvas.toDataURL('image/png')
</script>
4. LocalStorage / SessionStorage
// ========== LocalStorage ==========
// 数据持久存储,关闭浏览器后仍然保留
// 存储数据
localStorage.setItem('username', '张三')
localStorage.setItem('user', JSON.stringify({ id: 1, name: '张三' }))
// 读取数据
const username = localStorage.getItem('username')
const user = JSON.parse(localStorage.getItem('user'))
// 删除数据
localStorage.removeItem('username')
// 清空所有数据
localStorage.clear()
// 获取存储数量
console.log(localStorage.length)
// 遍历所有数据
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i)
console.log(key, localStorage.getItem(key))
}
// ========== SessionStorage ==========
// 会话存储,关闭标签页后清除,API 与 localStorage 相同
sessionStorage.setItem('token', 'abc123')
const token = sessionStorage.getItem('token')
// ========== 监听存储变化 ==========
// 在其他标签页修改 storage 时触发
window.addEventListener('storage', (e) => {
console.log('key:', e.key)
console.log('旧值:', e.oldValue)
console.log('新值:', e.newValue)
console.log('来源:', e.url)
})
// ========== 封装工具函数 ==========
const storage = {
set(key, value, expires) {
const data = {
value,
expires: expires ? Date.now() + expires : null
}
localStorage.setItem(key, JSON.stringify(data))
},
get(key) {
const item = localStorage.getItem(key)
if (!item) return null
const data = JSON.parse(item)
// 检查是否过期
if (data.expires && Date.now() > data.expires) {
localStorage.removeItem(key)
return null
}
return data.value
},
remove(key) {
localStorage.removeItem(key)
}
}
// 使用:存储 1 小时过期的数据
storage.set('cache', { data: 'test' }, 60 * 60 * 1000)
5. Drag and Drop
<style>
.drag-item {
width: 100px;
height: 100px;
background: #3498db;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: move;
margin: 10px;
}
.drop-zone {
width: 300px;
height: 200px;
border: 2px dashed #ccc;
display: flex;
align-items: center;
justify-content: center;
}
.drop-zone.over {
border-color: #3498db;
background: #ecf0f1;
}
</style>
<!-- 可拖拽元素 -->
<div
class="drag-item"
draggable="true"
id="item1"
>
拖拽我
</div>
<!-- 放置区域 -->
<div class="drop-zone" id="dropZone">
放置区域
</div>
<script>
const dragItem = document.getElementById('item1')
const dropZone = document.getElementById('dropZone')
// 拖拽开始
dragItem.addEventListener('dragstart', (e) => {
// 设置拖拽数据
e.dataTransfer.setData('text/plain', e.target.id)
e.dataTransfer.effectAllowed = 'move'
// 添加拖拽样式
e.target.style.opacity = '0.5'
})
// 拖拽结束
dragItem.addEventListener('dragend', (e) => {
e.target.style.opacity = '1'
})
// 拖拽进入放置区域
dropZone.addEventListener('dragenter', (e) => {
e.preventDefault()
dropZone.classList.add('over')
})
// 在放置区域上方移动
dropZone.addEventListener('dragover', (e) => {
e.preventDefault() // 必须阻止默认行为才能触发 drop
e.dataTransfer.dropEffect = 'move'
})
// 离开放置区域
dropZone.addEventListener('dragleave', (e) => {
dropZone.classList.remove('over')
})
// 放置
dropZone.addEventListener('drop', (e) => {
e.preventDefault()
dropZone.classList.remove('over')
// 获取拖拽数据
const id = e.dataTransfer.getData('text/plain')
const element = document.getElementById(id)
// 移动元素到放置区域
dropZone.appendChild(element)
})
</script>
6. Web Worker
// ========== 主线程 main.js ==========
// 创建 Worker
const worker = new Worker('worker.js')
// 发送消息给 Worker
worker.postMessage({
type: 'calculate',
data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
})
// 接收 Worker 返回的消息
worker.onmessage = (e) => {
console.log('计算结果:', e.data)
}
// 错误处理
worker.onerror = (e) => {
console.error('Worker 错误:', e.message)
}
// 终止 Worker
// worker.terminate()
// ========== Worker 线程 worker.js ==========
// 接收主线程消息
self.onmessage = (e) => {
const { type, data } = e.data
if (type === 'calculate') {
// 执行耗时计算(不会阻塞主线程)
const result = heavyCalculation(data)
// 返回结果给主线程
self.postMessage(result)
}
}
function heavyCalculation(arr) {
// 模拟耗时操作
let sum = 0
for (let i = 0; i < 1000000000; i++) {
sum += i
}
return arr.reduce((a, b) => a + b, 0)
}
// Worker 内部关闭自己
// self.close()
// ========== 内联 Worker ==========
// 不需要单独的 js 文件
const workerCode = `
self.onmessage = (e) => {
const result = e.data * 2
self.postMessage(result)
}
`
const blob = new Blob([workerCode], { type: 'application/javascript' })
const inlineWorker = new Worker(URL.createObjectURL(blob))
inlineWorker.postMessage(10)
inlineWorker.onmessage = (e) => {
console.log('内联 Worker 结果:', e.data) // 20
}
7. 其他新特性
// ========== Geolocation 地理定位 ==========
navigator.geolocation.getCurrentPosition(
(position) => {
console.log('纬度:', position.coords.latitude)
console.log('经度:', position.coords.longitude)
},
(error) => {
console.error('定位失败:', error.message)
}
)
// ========== History API ==========
// 添加历史记录
history.pushState({ page: 1 }, '标题', '/page1')
// 替换当前记录
history.replaceState({ page: 2 }, '标题', '/page2')
// 监听前进后退
window.addEventListener('popstate', (e) => {
console.log('状态:', e.state)
})
// ========== 新的表单特性 ==========
/*
<input type="email" required>
<input type="url">
<input type="number" min="0" max="100">
<input type="range" min="0" max="100">
<input type="date">
<input type="color">
<input type="search" placeholder="搜索...">
<input pattern="[0-9]{11}" title="请输入11位手机号">
*/
// ========== 新的选择器 API ==========
document.querySelector('.class')
document.querySelectorAll('div')
element.classList.add('active')
element.classList.remove('active')
element.classList.toggle('active')
element.classList.contains('active')
关键点
- 语义化标签:提升可读性和 SEO,常用 header/nav/main/article/section/aside/footer
- Video/Audio:原生多媒体支持,通过 source 提供多格式兼容
- Canvas:2D 绘图 API,适合图表、游戏、图像处理
- LocalStorage:持久存储 5MB,SessionStorage 会话级存储,都是同步 API
- Drag API:原生拖拽支持,核心是 dragstart/dragover/drop 事件
- Web Worker:独立线程执行耗时任务,通过 postMessage 通信,不能操作 DOM
目录