javaScript----浅谈一下下前端路由

54 阅读3分钟

前端路由的优缺点?

优点:传统的后端路由,访问新页面的时候需要向服务端发送新的请求,页面等待响应完成,这个过程有网络延迟。使用前端路由,在变换了路径的同时实现了无请求页面刷新。提高用户体验,同时用户在复制 url 后可以分享页面。

缺点:使用浏览器的前进,后退键的时候会重新发送请求,没有合理地利用缓存。

hash和history路由的区别?

  • history 利用了 html5 中新增的 pushStatereplaceState 方法。这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录 修改的功能(pushState将传入 url 直接压入历史记录栈,replaceState 将传入url替换当前历史记录栈)。

  • histroy 路由不会显示#,匹配的路径会全部传递给服务端。如果服务端并没有响应路由的路径,这个时候需要后端配合解决刷新 404 的问题。

  • hashurl# 后面的部分)虽然出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面,。

  • hash 改变时,会触发 hashchange 事件,监听该事件,对页面进行更新。

如何实现一个hash路由?

    <div>
      <ul>
        <li><a href="#/home">首页</a></li>
        <li><a href="#/user">用户中心</a></li>
        <li><a href="#/login">登陆</a></li>
      </ul>
      <div id="view"></div>
    </div>
    
<script>
  // 声明一个view
  let view = null;
  // 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完全加载。
  window.addEventListener("DOMContentLoaded", onload);
  // 监听hash的变化 hashchange用于监听hash值的变化
  window.addEventListener("hashchange", setViewChange);
  function onload() {
    view = document.getElementById('view')
    // 一开始进入页面匹配路由
    setViewChange();
  }
  function setViewChange() {
    if (!this.location.hash) {  //初始化路由
      view.innerHTML = "首页";
    }
    switch (this.location.hash) {
      case "#/home":
        view.innerHTML = "首页";
        break;
      case "#/user":
        view.innerHTML = "用户中心";
        break;
      case "#/login":
        view.innerHTML = "登陆";
        break;
    }
  }
</script>

解释:locationjavascript 里边管理地址栏的内置对象,而 location.hash 则可以用来获取或设置页面的标签值。比如 http://domain/#admin的location.hash="#admin"。 可以根据 location.hash 的不同匹配不同的页面展示。服务端只会解析 # 之前的路径,# 之后的路径 hash 会匹配解析。

pushState和replaceState的区别是?

当我们每一次调用 pushState 的时候,浏览器的历史栈中就会存入当前的状态对象,当去操作浏览器的前进和后退的时候就会更新浏览器的路由。并且触发 popstate 事件。(注意:history.pushState()history.replaceState() 调用的时候不会触发 popstate 事件。)pushState会增加一条新的历史记录,而 replaceState 则会替换当前的历史记录,replaceState 的用法和 pushstate 的一样。

history.pushState的用法?

history.pushState 方法接受三个参数,依次为:

state:一个与指定网址相关的状态对象,popstate 事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。可用它来传一些数据

title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。

url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。

如何实现一个history路由?

<ul>
    <li><a href="?x=home" onclick="changeUl('home');return false">首页</a></li>
    <li><a href="?x=user" onclick="changeUl('user');return false">用户中心</a></li>
    <li><a href="?x=login" onclick="changeUl('login');return false">登陆</a></li>
</ul>
<div id="view">

<script>
  const view = document.getElementById('view')
  function changeUl(val) {
    let state = val
    //每一次执行pushState都会在浏览器的地址栏中增加新的网址
    history.pushState(state, null, '?x=' + val);
    setViewChange(val)
  }

  // 设置需要展示的页面
  function setViewChange(val) {
    if (!val) {  //初始化路由
      val = 'home'
    }
    switch (val) {
      case 'home':
        view.innerHTML = '首页'
        break
      case 'user':
        view.innerHTML = '用户中心'
        break
      case 'login':
        view.innerHTML = '登陆'
        break
    }
  }
  window.addEventListener('DOMContentLoaded', onload)
  function onload() {
    // 一开始进入页面匹配路由
    setViewChange()
  }
  // popstate是浏览器某些行为下触发的事件。
  window.addEventListener('popstate', function (e) {
  // console.log(e);
    setViewChange(e.state)
  });
  // 与popstate用法相同
  // onpopstate = function (event) {
  //   console.log(event);
  // }
</script>

解释:每次 pushState 方法执行的时候都会向地址栏中添加新的历史纪录,同时浏览器的地址栏会显示新的地址,这样就实现了展示内容和地址的统一,当我们操作浏览器前进和后退的时候需要监听 popstate 中的state去设置当前展示的页面。

什么是popstate?

官方解释:每当激活同一文档中不同的历史记录条目时,popstate 事件就会在对应的 window 对象上触发。如果当前处于激活状态的历史记录条目是由 history.pushState() 方法创建的或者是由 history.replaceState() 方法修改的,则 popstate 事件的 state 属性包含了这个历史记录条目的 state 对象的一个拷贝。

简单来说:popstate 中存在浏览器历史记录栈中所有历史纪录,同时 popstate 是浏览器的行为才能触发,这样当我们需要操作浏览器前进后后退时,通过监听 popstate 可以实现页面的更新。(前提是在 pushState 时传入了 state 状态)