因为 AJAX 的出现诞生了单页应用这种网页类型,单页应用简单的说就是前端通过 AJAX 加载和动态改变 DOM 内容来切换页面,网页本身并不会刷新和跳转。像 YouTube 、Google Play 、网易云音乐 等 都属于单页应用。虽然页面不会跳转但观察浏览器地址栏就会发现地址是会改变的,手动刷新网页也不会转到首页,这就是前端实现的路由。
目前常见的实现路由的方式有两种,一种是通过 hash
来实现,另一种是通过 HTML5 中加入的 history
API 来实现。
hash
这里主要是实现改变 URL,AJAX 的部分就不写了,下面是一个简单的 HTML:
HTML
<div>无内容</div>
<ul>
<li><a href="#red">红色</a></li>
<li><a href="#green">绿色</a></li>
<li><a href="#blue">蓝色</a></li>
</ul>
只需要在链接 URL 前面加一个 #
链接就不会跳转。这里要实现的功能就是点击链接后 URL 改变,div
中的内容也改变,刷新网页 div
中的内容也不会消失,下面是 JS 代码:
JavaScript
// 封装一个函数,根据传入的 hash 改变 div 的内容
let setPage = hash => {
// 如果 hash 没有内容
if (hash == '' || hash == null) {
hash = 'white';
}else {
hash = hash.replace('#', ''); // 去除 #
}
// div 的内容
let content = {
red: "红色",
green: "绿色",
blue: "蓝色",
white: "无内容"
};
// 根据传入的 hash 改变 div 的内容
document.querySelector('div').innerHTML = content[hash];
// 根据传入的 hash 改变 div 的背景颜色
document.querySelector('div').style.background = hash;
// 根据传入的 hash 设置页面标题
document.title = content[hash];
};
// 给 window 添加一个 hashchange 事件,当 hash 改变就会触发 hashchange 事件
window.addEventListener('hashchange', (event) => {
setPage(location.hash); // 根据获取的 hash 改变 div 的内容
});
// 执行 setPage 函数,刷新页面 div 的效果也不会消失
setPage(location.hash);
因为注释比较多 看上去可能比较长,实际很简单,下面是详细说明:
location.hash 属性
如果 URL 中包含 #
通过 location.hash
可获取 #
和后面的内容。location.hash
是一个可读可写的属性,直接修改 location.hash
的内容 URL 也会改变。
hashchange 事件
当窗口 URL #
后面的内容改变时就会触发 hashchange
事件,hashchange
还包含两个属性:
event.newURL
当前页面的完整 URL。
event.oldURL
前一个 URL,也就是更改之前的 URL。
setPage
函数封装了 改变 div
的内容和背景颜色、改变页面标题,当 hashchange
监听到 URL 变化时就会调用 setPage
函数,刷新或打开页面也会调用 setPage
函数。使用 hash
路由最合兴的就是 location.hash
属性 和 hashchange
方法,hashchange
方法需要绑定到 window
。
下面是实现效果:
在历史记录中也能看到:
注意!如果链接 URL #
后面的内容和页面元素的 id
相同 在点击链接时会跳转到相同 id
元素的区域。
history
history
是 HTML5 中加入的 API,主要功能就是操作浏览器的会话历史记录,下面是 HTML:
HTML
<div>无内容</div>
<ul>
<li><a href="red">红色</a></li>
<li><a href="green">绿色</a></li>
<li><a href="blue">蓝色</a></li>
</ul>
这里要实现的功能还是点击链接改变 URL 和 div
的效果,同时添加历史记录,下面是 JS:
JavaScript
let link = document.querySelectorAll("li a"); // 获取链接
// 封装一个函数,根据传入的 data 改变 div 的内容
let setPage = data => {
// div 的内容
let content = {
red: "红色",
green: "绿色",
blue: "蓝色",
white: "无内容"
};
// 根据传入的 data 改变 div 的内容
document.querySelector('div').innerHTML = content[data];
// 根据传入的 data 改变 div 的背景颜色
document.querySelector('div').style.background = data;
// 根据传入的 data 设置页面标题
document.title = content[data];
};
for (let i = 0; i < link.length; i++) {
// 链接点击
link[i].addEventListener("click", event => {
event.preventDefault(); // 阻止浏览器跳转
let el = event.target; // 获取当前点击的链接
// 修改 URL 和历史记录
history.pushState(el.getAttribute('href'), '', el.href);
// 根据点击链接的 href 来设置 div 的效果
setPage(el.getAttribute('href'));
});
}
// 给 window 添加 popstate 事件,点击浏览器的前进和后退就会触发 popstate
window.addEventListener('popstate', event => {
let data = event.state; // history.pushState 传入的数据
// 如果没有数据
if (data == undefined) {
data = 'white';
}
// 根据 history.pushState 传入的数据来设置 div 的效果
setPage(data);
});
这里也是因为注释比较多,实际很简单,下面是详细说明:
history.pushState(data, title, url) 方法
在不跳转的情况下改变 URL,同时添加到历史记录,下面是参数说明:
| 参数 | 类型 | 说明 | |-------|--------|---------------------------| | data | state | 一个状态对象,可以通过 popstate 事件读取 | | title | string | 标题,对大多数浏览器都无效。 | | url | string | 要添加到历史记录的 URL |
history.replaceState(data, title, url) 方法
在不跳转的情况下改变 URL,同时替换历史记录,和 history.pushState
不一样的地方就是 history.replaceState
只会替换历史记录,不会添加历史记录,也就是说无论执行多少次都只会有一条记录,参数可以参考 history.pushState
的参数。此方法在这里暂时没有用到。
popstate 事件
当浏览器前进或者后退时就会触发 popstate
事件,注意!只有在同一个文档前进或者后退才会触发 popstate
事件,不同文档之间跳转并不会触发 popstate
。popstate
也包含一些属性:
event.state
获取 history.replaceState
或 history.pushState
设置的状态对象。
history.back() 方法
移动到上一条历史记录,类似于浏览器的后退按钮。这里暂时没有用到此方法。
history.forward() 方法
移动到下一条历史记录,类似于浏览器的前进。这里暂时没有用到此方法。
history.go() 方法
接收一个数值,以当前 URL 为基准移动到指定的 URL,例如 history.go(-1)
就是后退一次,history.go(1)
就是前进一次,history.go(0)
就是直接刷新当前页面。此处暂时没有用到此方法。
history.back()
、history.forward()
、history.go()
都能触发 popstate
事件。
setPage
函数封装了更改 div
的标题、背景颜色,更改页面标题。因为 history.pushState
不会触发 popstate
事件,所以在点击按钮时还需要调用 setPage
函数来设置 div
的效果。
注意!直接使用 .href
和 getAttribute('href')
获取的属性是不一样的,.href
获取的是完整的 URL,getAttribute('href')
只能获取 href
中的内容。
history
路由最合兴的就是 history.pushState
方法 和 popstate
事件,popstate
事件需要绑定到 window
。
下面是 history
路由的效果:
注意!如果使用 history
路由 服务器需要设置 404 重定向,把 404 重定向到首页,否则刷新网页或访问历史记录会出现 404 。
版权声明:本文为原创文章,版权归 Mr. Ma's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/788/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。