Skip to content

第三章练习答案 ​

URL、History 与本地存储 ​

js
const state = { page: 2, filter: 'open' }
const params = new URLSearchParams(state)
history.pushState(state, '', `?${params}`)
localStorage.setItem('last-view', JSON.stringify(state))
console.log(location.search, JSON.parse(localStorage.getItem('last-view')))

刷新后 URL 查询参数仍在,localStorage 快照也能恢复;但 pushState() 不会自动触发 popstate,只有用户前进/后退或脚本调用 history.back() 才需要在 popstate 中重新渲染。

URL、URLSearchParams 与编码 ​

js
const url = new URL('https://example.test/list?q=a%2Bb&page=0')
const page = Number.parseInt(url.searchParams.get('page') || '1', 10)
const safePage = Number.isInteger(page) && page > 0 && page <= 100 ? page : 1
console.log(url.searchParams.get('q'), safePage, url.searchParams.toString())

get('q') 返回 a+b,而不是把加号再次当作空格;页码 0 被边界规则归一为 1。写回 URL 时使用 URLSearchParams,不要手拼未编码的查询字符串。

pushState、replaceState 与 popstate ​

js
function render() { document.querySelector('#page').textContent = new URL(location.href).searchParams.get('page') || '1' }
addEventListener('popstate', render)
history.pushState({ page: 2 }, '', '?page=2')
render()
history.replaceState({ page: 3 }, '', '?page=3')
render()

pushState 增加历史条目,replaceState 只替换当前条目;两者都不会自动触发 popstate,所以脚本要显式调用 render()。点击后退时,监听器读取新的 location 再渲染。

localStorage 版本迁移与事件 ​

js
localStorage.setItem('settings', '{bad json')
const result = readSettings()
console.log(result.version, result.density, localStorage.getItem('settings'))

损坏 JSON 会返回版本 2 的默认对象并覆盖存储;版本 1 会补上 density 后写回版本 2;版本 2 保留已有值。两个同源标签页中,写入页面不会收到自己的 storage 事件,另一个页面会收到 key、oldValue 和 newValue。

用心记录每一步成长