前端路由的实现

前端路由的两种实现方式

路由是什么?

路由一种根据请求的内容来匹配相应执行代码的一种机制, 在前端应用上面来说, 就是通过不同的路径来请求不同的资源。对于前端应用, 路由可以分为前端路由以及后端路由两种类型。

后端路由:

在spa单页面应用出来之前, 最常用的一种渲染方式是服务端渲染(SSR), 主要的方式是通过服务器返回页面上需要呈现的内容, 因此, 需要页面呈现什么的内容, 如何根据请求的不同路径返回不同的资源是由服务器端进行配置的,使用服务器端进行渲染有如下几个优缺点:优点:
  • 有利于 SEO 优化。
  • 首屏加载速度快。
缺点:
  • 每次请求都是渲染一个新的页面,页面重新进行刷新, 旧的页面会被丢失, 从而造成性能上的影响。

前端路由:

前端路由是单页面应用中页面切换时的资源请求方式, 前端路由会通过url的改变匹配获取到请求参数,根据请求参数的不同 在一个页面中加载不同的资源, 通过这种方式,可以跳转到不同的页面并且不会刷新页面。优点:
  • 除了首屏之外的页面能够快速响应, 因为每次切换页面都只需要加载少量数据。
  • 组件的复用度高, 提高页面加载性能。
  • 前后端分离开发。
  • 当页面进行切换的时候的 transiton 或者 animation 动画更容易被应用。
缺点:
  • 首屏资源加载速度慢, 因为对于单页面应用, 页面渲染相关的逻辑位于js文件中,js 文件会在浏览器解析 html 之后加载, 因此会造成首屏加载时的白屏问题。
  • SEO 性能差。
  • 首次加载比较慢, 因为整个网站的资源需要在首次加载页面的时候全部加载。

前端路由的实现方式:

更新视图但不重新请求页面时前端路由的核心之一。实现前端路由主要有两种模式, hash 以及 history 模式。

hash:

hash 又被称作锚点, 本来用于放在 url 中指定网页中的位置, hash 指的是url 中 # 符号之后的字符, 这个值可以通过 window.localtion.hash 获取到值。hash 值时用于浏览器端的, 对于服务器端没有作用, 不会包含在 http 请求中, 改变 hash 值不会重新加载页面。可以通过使用监听 hashchange 监听 hash 值的改变:
1
window.addEventListener('hashchange', func, false);
这样我们就可以在 hash 值发生变化的时候触发 func 函数, 从而更新视图。
history:
history 模式主要是通过使用 window.history 只读属性从而对于浏览器历史记录栈进行读取信息和操作。
window.history 是指向浏览器历史记录栈的只读对象, 提供了操作浏览器历史记录栈的接口
window.history 提供了一些方法用于操作浏览器的页面行为:window.history.back(); : url 回退, 类似于点击浏览器上方的回退按钮。window.history.forward(); url 前进, 类似于点击浏览器上方的前进按钮。window.history.go(1): 前进到下一个页面。与 forward 相同。window.history.go(-1): 回退到上一个页面, 和 back 相同。 在 HTML5 中, 新增了两个新的 API: pushStatereplaceState.
1
2
window.history.pushState(state, title, url);
window.history.replaceState(state, title, url);
使用这两种方法修改浏览器历史记录栈之后, 虽然改变了当前的 url, 但是浏览器不会立即发送这个 url, 这就实现了更新视图但是不会请求页面的作用。这两个 api 都有三个参数:
  • 状态对象(state object):一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。
  • 标题(title):FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。
  • 地址(URL): 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的URL不一定是绝对路径;如果是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。
使用 pushState 用于增加一条新的历史记录, 使用 replaceState 将会替换掉当前的历史记录。当活动历史记录中的条目更改的时候, 将会触发 popstate 事件, 例如点击浏览器的回退按钮, 当事件被触发的时候, 事件的 state 属性为使用 pushState 或者 replaceState 中传入的参数 state
1
2
3
4
5
const state = { bar: 'foo' };
window.history.pushState(state, '', 'route');
window.addEventListener('popstate', function (e) {
console.log('state', e.state); // { bar: 'foo' }
});
两种路由实现方式的区别:
  • 使用 history 模式可以设置任意和当前 url 同源的 url ,但是使用 hash 只能设置 # 号之后的数值。
  • 使用 history 的 pushState 可以设置相同的 url ,这个新的 url 也会被存放在记录中, 而 hash 值只有和之前的 url 不同才会被记录到 url 中。
  • 在 pushState 中通过传入的 state 值可以添加任何类型的数据, 而 hash 值只可以添加短字符。