SPA的原理介绍

287 阅读1分钟

楔子

众所周知,当前前端应用最重要的一种实现方式就是单页应用。单页应用有着良好用户体验和减轻服务器的优点,单页也存在seo的相关方面问题。但是这个不是今天讨论的重点,我们今天的重点是之所以能够实现spa的效果,浏览器为我们提供哪些基础设施。

history和hash模式

history url比较优美,但是部署上线的时候需要对应的后端兼容请求不到资源的情况

hash模式兼容性比较好但是很多人认为#作为url不够优雅

有助于理解spa底层实现原理的例子

<!--
1. History的pushState replaceState 不会触发popstate事件,History的go back forward会触发,这个时候需要包装pushState 和 replaceState方法 然后派发一个事件出来进行
var _wrapper = function(type) {
   var orig = history[type];
   return function() {
       var rv = orig.apply(this, arguments);
      var e = new Event(type);
       e.arguments = arguments;
       window.dispatchEvent(e);
       return rv;
   };
};
history.pushState = _wrapper('pushState');
history.replaceState = _wrapper('replaceState');


-->
<ul class="history">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

<script>
  document.querySelectorAll(".history")[0].addEventListener('click', function (e) {
    let node = e.target
    if(node.tagName === 'LI'){
      let value = node.textContent
      history.pushState({text: value}, value, '/'+value)
    }
  })

  window.onpopstate = function (e) {
    console.log(e)
  }
</script>


<!--
1. hash模式可能不太美观,但是兼容性比较好
2. 另外hash的变化会先出阿发popstate事件,然后在出发hashchange事件(注意)

-->

<ul class="hash">
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

<script>
  document.querySelectorAll(".hash")[0].addEventListener('click', function (e) {
    let node = e.target
    if(node.tagName === 'LI'){
      let value = node.textContent
      location.hash = `#${value}`
    }
  })

  window.onhashchange = function (e) {
    console.log(e)
  }
</script>