Skip to content

浅谈前端路由

什么是路由?

简而言之就是 if...else...

什么是前端路由?

暂且不说理论,我们通过一个个例子来理解前端路由。

小栗子

例1:我们来做一个状态切换,代码如下:

预览链接: Demo

此时,我们实现了以下效果:

  • 点击tab-1,出现对应的 content-1 的内容
  • 点击tab-2,出现对应的 content-2 的内容

现在,我们设置默认选中 tab-1,刷新页面以后,我们选中 tab-2,此时,我们刷新页面或者是将此页面分享给别人,打开页面以后又回到了 tab-1

预览链接: Demo

那么,我们想,怎么才能让我们当前页面状态在刷新以后不改变呢?

​ 大部分前端er都知道,jsbin最大的功能就是可以保存当前页面所有信息,在保存了当前链接以后,当前页面的url会改变,记录了当前页面的状态信息,即时刷新页面内容也不会丢失,这样有助于我们将代码分享给别人。

那么,我们怎样可以像 jsbin 一样可以保存当前页面的状态信息呢?

使用哈希

受到 jsbin 的启发,我们知道可以使用 url 来记录当前页面的信息,那么,我们怎么使用 url 来记录呢?

答案:使用哈希来保存当前页面装状态信息

通过上面的代码我们知道,当我们点击 tab-1 的时候会发生相应的变化,那么,我们可以通过 index 来记录用户点击的是第几个 tab, 使用hash 来记录这个状态。

预览链接: Demo

此时,每个选中的 li 都有一个对应的hash 存入 location ,那么每次点击切换的时候都是通过获取它对应的 hash 来切换其状态。

同时,我们将链接复制到另一个窗口上打开依然是原来的状态,此时,我们就简单的实现了刷新页面当前状态不改变,同时当前状态可分享给别人

使用< a href="" >标签 和监听哈希变更事件

上面的例子我们看到,其实我们点击事件保存的就是形如 后缀为#0#1 这样的url ,此时我们想,这不是和 <a href="#0"> 很相似吗?那我们为什么不用 <a href=""> 的锚点来切换对应的状态呢?

此时,我们点击 tab 的时候更改的是 url ,那么变化的是 url ,我们就不要监听 click 事件了,我们监听 url 吧。

通过mdn知道,监听 url 变化使用 hashchange

预览链接:Demo

使用这种方式改变状态,突然见豁然开朗,原来使用简单的 a 标签也可以做到,同时 js 代码也精简了很多。

但是,这种方式也有一些问题,就是它容易被其他的 a 标签所覆盖,我们来看个例子:

假设当前页面有很多个 p 标签,下面有个跳转到顶部的 a 标签。

代码链接:Demo

原本我们已经选中了 tab-2 ,但是点击了回到顶部以后原来的状态被覆盖了,因此在刷新页面的时候就没有了原来的状态,同时分享在其他窗口打开链接的时候也是如此。

使用路径代替锚点表示状态

上面的例子中我们知道,如果在 a 标签中使用锚点表示某个状态,容易被其他的锚点所覆盖,那么我们可以使用路径来替换锚点表示状态,形如 <a href="/xxx"></a>

此时,可能有人会说:不可能的,你如果使用路径的话肯定是要跳转页面的,而如果你后台如果没有这个路径对应的返回信息的话,返回的肯定是 404!注定跳转失败。

的确如此,但是,我们想要的是使用 url 来表示状态,而不是用其跳转页面啊,因此,我们只有一个办法:

阻止<a href="/xxx"> 的默认事件,使其不能跳转页面。

代码链接:Demo

部分代码说明

js

selectTab()

$('tab').on('click','.nav > li > a',(e)=>{
  
  e.preventDefault() //阻止默认事件
  
  let a = e.currentTarget //获得当前选中的a
  
  let path = a.getAttribute('href') 
  //拿到结果为形如 "/tab1" 的路径。
  //此处不使用 a.attribute('href') 来获得对应 路径,因为返回为 
  //'http://127.0.0.1:8080/tab1' 的路径不是我们要的
  
  window.history.pushState({},'abc',path)  //  使用path路径添加一个状态
  selectTab()
})

此时,我们就可以很好的在实现状态切换的同时,不会受到 a 标签锚点的影响。

但是,此时的页面状态是可分享的吗?刷新以后是什么样的情况呢?

答案是:返回 404 !因为 后台没有这个路径的路由信息。

此时,我们要自己写一个后端路由来模拟实现刷新页面后不跳转页面。即,当路径为 / 或者/tab1 或者 /tab2 的时候都是返回同一个页面。

前端代码链接 :Demo

后端核心代码如下:

js
if(path === '/' || path === '/tab1' || path === '/tab2'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    let string = fs.readFileSync('./index.html','utf8')
    response.write(string)
    response.end()
  }else{
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write('呜呜呜')
    response.end()
  }

预览效果:

小结

以上,我们就实现了无刷新更改页面状态 ,接下来我们来说一说什么是前段路由

<tab>
  <ol class="nav">
    <li><a href="./tab1">tab-1</a></li>
    <li><a href="./tab2">tab-2</a></li>
  </ol>
  <ol class="content">
    <li>content-1</li>
    <li>content-2</li>
  </ol>
</tab>
  <a href="/xxx">回到顶部</a>

上面代码中,因为后台代码已经对 //tab1/tab2 都是返回同一个 页面

此时我们再来回顾以下什么是路由

就是你给我一个路径,我给你返回一个页面(后端路由)

你给我一个路径,我切换一个状态(前段路由)

此处的 tab-1tab-2 就是前端路由。 点击 a 标签无跳转

**而 <a href="/xxx"> 就是后端路由 ** , 点击 a 标签跳转到 /xxx 路径

以上的前端路由,也就是 Vue-Router 中 <router-link></router-link>的实现原理

具体参考Vue-Router

推荐阅读: