!
也想出现在这里? 联系我们
广告区块

路由原理

前端路由原理

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

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

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

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

hash实现

  • hash是URL中hash(#)及后面的部分,常用作锚点在页面内进行导航,改变URL中的hash部分不会引起页面刷新
  • 通过hashchange事件监听URL的变化,改变URL的方式只有这几种:
    1. 通过浏览器前进后退改变URL
    2. 通过<a>标签改变URL
    3. 通过window.location改变URL

history实现

  • history提供了pushStatereplaceState两种方法,这两种方法改变URL的path部分不会引起页面刷新
  • history提供类似hashchange事件的popstate事件,但popstate事件有些不同
    1. 通过浏览器前进后退改变URL时会触发popstate事件
    2. 通过pushState/replaceState<a>标签改变URL不会触发popstate事件
    3. 可以拦截pushState/replaceState的调用和<a>标签的点击事件来检测URL变化,所以监听URL变化可以实现,只是没有hashchange那么方便

原生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;
  }
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
有新私信 私信列表
搜索