1.路由是什么

  • 搞清楚这几个概念:
  • 路由
  • 分发
  • 路由表
  • 默认路由
    如果没有#n,就给一个默认值
    number = number || 1;
  • 404 路由 / 保底路由
    如果用户输入了错误路径,就给一个404页面,保证用户总是能够看到一个页面
  • 嵌套路由

1.1 路由器

  • 如果家里有1个即以上的人要上网,就需要一个路由器
  • 上网路由
    1.用户上网连接路由器,路由器看你想连哪里,就会把信号包发给相应的地方(百度、抖音、腾讯等)
    2.分发:分别发送到各个地方
    3.路由就是分发请求,路由器就是分发请求的东西
    4.路由都是一对多的(一个用户可以发送多个请求到不同地方)
  • 总结:分发请求的对象就是路由

1.2 前端路由

  • 路由表:一个存储到各个目的地的最佳路径的表
    1.路由根据路由表来传送
    2.所有框架实现路由都有路由表
  • 前端路由
    根据用户提供的url是:http://127.0.0.1/#1、#2、#3、#4,分别展示DIV1、DIV2、DIV3、DIV4界面
  • hash:hash就是url中#及其后面的内容
    1.可通过:window.location.hash获得url中的 #xxx
    2.修改页面hash:<a href="#1">go to 1</a>通过a标签可以改变hash的值
    3.监听hash变化:当URL的片段标识符更改时,将触发hashchange事
    —— 跟在#符号后面的URL部分,包括#符号
    ——window.addEventListener("hashchange",()=>{})
  • 代码优化逻辑
    1.默认路由:如果没有给任何路径,则给默认值
    ——number = number || 1
    2.404:给了错误路径,给一个404路由
//最简单的路由实现
//HTML中
<a href="#2">go to 2</a>
<div class="app"></div>
<div style="display=none" id="div1">1</div>
<div style="display=none" id="div1">2</div>
<div style="display=none" id="div1">3</div>
<div style="display=none" id="div1">4</div>
<div style="display=none" id="div404">404</div>

//JS中
const number = window.loacation.hash.substr(1)
number = number || 1 //默认路由:number不存在就取1
const div = document.querySelector(`#div${number}`)
const app = document.querySelector(`#app`)
div.display = 'block'
app.appendChild(div)
window.addEventListener("hashchange",()=>{
  //重新获取hash,将新的div放到div#app中显示
}

1.3 路由表

  • hash和div的关系是可以自定义的
    比如:hash给了1,可以找 div1或者 divone
const div1 = document.createElement("div")
div1.innerHTML = "1"
//234同理
const routeTable = {
  // 表驱动编程,这样写了HTML里面就不需要div了
  "1": div1,
  "2": div2,
  "3": div3,
  "4": div4
};

function route(){//渲染路由
 let number = window.location.hash.substr(1)
 const app = document.querySelector(`#app`)
 //根据表来寻找对应的div
 let div = routeTable[number.toString()];
 //获取界面、渲染界面代码省略
 app.appendChild(div)
}

1.4 嵌套路由

  • 如果#1界面里面还有几块子界面:#1/1、#1/2、#1/3
    1.那么就不是在app里面路由,而是在div1里面做路由
    2.所以要给 route 函数一个参数container,也就是要在哪里路由,容器是哪一个
    3.这样就不需要 app 这个参数了,而是直接container代替
    4.后面再调用route的时候就需要传参:app
  • 和之前的路由一样,给一个hash表:route1Table
  • 后面的思路
    1.把1/1分割成两个部分:[1,1]
    2.第一个1就用第一层路由去渲染,就得到了div1
    3.第二个1就用第二个路由去渲染,就在div1里面得到了div11
  • 路由可以再分层
function route(container){//渲染路由
 let number = window.location.hash.substr(1)
 //把1/1分割成两个部分:[1,1],分割前后两个数字,根据两个路由表来寻找对应的div
 let div = routeTable[number.toString()];
 container.innerHTML = ''
 container.appendChild(div)
}
router(div1) //router(app)

2.路由的三种模式

  • hash 模式:代码
    任何情况都可以用hash做前端路由
    缺点:SEO不友好,服务器收不到hash
    ——浏览器是不会把#后面的内容发给服务器的
    ——无论访问 baidu.com/#xxx 都默认访问 baidu.com/,永远展示默认路由
    谷歌有专门针对hash的SEO,但没什么用
  • history 模式:代码
    使用场景:后端将所有前端路由都渲染同一页面
    用户不管请求什么都到同一个页面(不能是404页面)
    ——baidu.com/xxxx 不论/后面输入什么都到首页
    缺点:IE8以下不支持
  • memory 模式:代码
    既不用hash,也不用history,用对象来存储
  • 三种模式的区别
    1.前面两种模式都是路径存在url上面(前者是存的hash,后者是路径)
    2.memory是单机路由,不可分享

2.1 hash模式

  • 从hash中得到number
    let number = window.location.hash.substr(1);
    有#号,要去掉
  • 路径:/#1

2.2 history 模式

  • codesandbox网页就支持这个模式
    不论用户后面输入什么乱码(没有路由的情况),都是首页
  • 区别
    1.从pathname得到number
    let number = window.location.pathname
    ——获得:/1
    2.routeTable中的key要变成"/1"
    3.a标签中的href由 #n 变成 /n
  • 路径:/1
    不需要#
    在这里插入图片描述
  • 目前的体验:每次点击都要重新渲染页面,很慢
  • 解决:history API
//点击a标签,阻止默认事件,跳转到页面
a.addEventListener("click",e=>{
  e.preventDefault()
  const href = a.getAtrribute("href")
  window.history.pushState(null, `page ${href}`, href);
  onStateChange(href) //通知state改变,并传参数
})
function onStateChange(){
  route(app)
}

2.3 hash模式和history模式对比

  • 使用条件不用
    1.hash模式在任何条件都可以使用,但SEO不友好,服务器收不到hash
    2.history模式:后端将所有的页面都渲染到同一个非404页面;IE8不支持
  • number的获取方式不同
  • a标签的点击事件不同
    1.history需要阻止默认事件:刷新页面
    2.得到href,然后通过window.history.pushState去相应的href,页面就会在不刷新的情况下变更
  • 没有可监听的事件,需要手动通知href改变,然后调用router函数,重新渲染页面
  • 默认页面不同
    1.history:number默认是/,是存在的,因此要判断
    2.hash:默认不存在
  • 点击a标签后,默认做两件事
    1.改变url默认不刷新页面
    2.重新路由

2.4 memory 模式

  • hash和history都有一个共同点
    把所有数据存在路径后面,不论是/1还是/#1,这里的东西一变,所有的东西都改变
    在这里插入图片描述
  • memory不用这个地方,这里不改变,页面不改变
    使用localstorage
    在这里插入图片描述
  • 优点
    这种模式适合非浏览器
    比如说app里面做路由,app里面没有路径,不是网页,就用memory模式
  • 缺点:没有url
    只对单机有效
    页面没有链接 复制给别人只能进入初始状态

3.Vue-Router 源码

Logo

前往低代码交流专区

更多推荐