前端路由原理

路由的概念来源于服务端,描述URL与处理函数之间的映射关系。

在web前端单页应用SPA中,路由描述URL与UI之间的映射关系,这种映射是单向的,即URL变化引起UI更新(无需刷新页面)。

要实现前端路由,需要解决两个核心:

  1. 如何改变URL却不引起页面刷新?
  2. 如何检测URL变化?

hash实现

history实现

原生JS前端路由实现

基于hash实现

<ul>
    <li><a href="#/home">home</a></li>
    <li><a href="#/about">about</a></li>
</ul>
<div id="routeView"></div>

//页面加载完不会触发hashchange,这里主动触发一次hashchange事件
window.addEventListener('DOMContentLoaded', onload);
//监听路由变化
window.addEventListener('hashchange', onHashChange);

//路由视图
var routerView = null;

function onload() {
  routerView = document.querySelector('#routeView');
  onHashChange();
}

//路由变化时,根据路由渲染对应UI
function onHashChange() {
  switch (location.hash) {
    case '#/home':
      routerView.innerHTML = 'Home';
      return;
    case '#/about':
      routerView.innerHTML = 'About';
      return;
    default:
      return;
  }
}

基于history实现

<ul>
    <li><a href="/home">home</a></li>
    <li><a href="/about">about</a></li>
</ul>
<div id="routeView"></div>

//页面加载完不会触发hashchange,这里主动触发一次hashchange事件
window.addEventListener('DOMContentLoaded', onload);
//监听路由变化
window.addEventListener('hashchange', onPopState);

//路由视图
var routerView = null;

function onload() {
  routerView = document.querySelector('#routeView');
  onPopState();
}

//拦截<a>标签点击事件默认行为,点击时使用pushState修改URL并手动更新UI
//从而实现点击链接更新URL和UI的效果
var linkList = document.querySelectorAll('a[href]');
linkList.forEach(el => el.addEventListener('click', (e) => {
  e.preventDefault();
  history.pushState(null, '', el.getAttribute('href'));
  onPopState()
}));

//路由变化时,根据路由渲染对应UI
function onPopState() {
  switch (location.pathname) {
    case '/home':
      routerView.innerHTML = 'Home';
      return;
    case '/about':
      routerView.innerHTML = 'About';
      return;
    default:
      return;
  }
}