vue-router原理

前端路由

什么是前端路由

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

如何实现前端路由

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

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

目前主要有两种实现方式,分别是hash和history。

hash实现

hash是URL中hash(#)及后面的那部分,常用作锚点在页面内进行导航,改变URL中的hash部分不会引起页面刷新。

通过hashchange事件监听URL的变化,改变URL的方式只有以下这几种:

  1. 通过浏览器的前进后退改变URL
  2. 通过标签改变URL
  3. 通过window.location改变URL
  4. 通过手动修改改变URL

history实现

history提供了pushState和replaceState两个方法,这两个方法改变URL的path部分,不会引起页面刷新

history提供类似hashchange事件的popstate事件,但popstate事件有些不同:

  1. 通过浏览器前进后退改变URL时会触发popstate事件
  2. 通过pushState/replaceState或标签改变URL不会触发popState事件
  3. 但是我们可以拦截pushState/replaceState的调用和标签的点击事件来检测URL变化
  4. 通过js调用history的back,go,forward方法触发该事件

所有history监听URL变化可以实现,但是没有hashchange那么方便,但是用户体验上相对会更好,因为在URL上不会出现#。

利用原生js简单实现hash和history

原生js实现hash

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <ul>
    <!-- 定义路由 -->
    <li><a href="#/home">home</a></li>
    <li><a href="#/about">about</a></li>
  </ul>

  <!-- 渲染路由对应的UI -->
  <div id="routerView"></div>
</body>
  <script>
    let routerView = document.querySelector('#routerView');
    // 通过hashchange监听URL的变化,渲染对应的UI
    window.addEventListener('hashchange', ()=>{
      let hash = location.hash;
      routerView.innerHTML = hash
    })
    // 监听页面加载完成后,将当前路由对应的UI进行渲染
    window.addEventListener("DOMContentLoaded",()=>{
      if(!location.hash){ //如果不存在hash值,那么重定向到/
        location.hash = '/'
      }else{ //如果存在hash值,那就渲染对应的UI
        let hash = location.hash;
        routerView.innerHTML = hash
      } 
    })
  </script>
</html>

原生js实现history

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <ul>
    <!-- 定义路由 -->
    <li><a href='/home'>home</a></li>
    <li><a href='/about'>about</a></li>
    <!-- 渲染路由对应的UI -->
    <div id="routeView"></div>
  </ul> 
</body>
  <script>
    let routerView = routeView;
    window.addEventListener('DOMContentLoaded', onLoad);
    window.addEventListener('popstate', ()=>{
      routerView.innerHTML = location.pathname;
    })
    function onLoad(){
      routerView.innerHTML = location.pathname;
      var linkList = document.querySelectorAll('a[href]');
      linkList.forEach(el => el.addEventListener('click', function(e) {
        e.preventDefault();
        history.pushState(null, '', el.getAttribute('href'));
        routerView.innerHTML = location.pathname;
      }))
    }
  </script>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值