初探路由模块知识。

    1. 路由的分类:
      • 前端路由(SPA应用中 Hash / History);
      • 后端路由(也称为服务器路由);
    2. 后端路由:
      当服务器接收到客户端发送的 HTTP 请求之后,就会根据请求中的 URL 找到相应的映射函数,并且执行映射函数,最后将映射函数的返回值返回给客户端。
      静态资源服务器,所有的 URL 映射函数就是对文件的读取操作;
      动态服务器,映射函数可能是读取数据库的数据,或者对数据做一些处理,等等。然后将这些数据处理结果或者文件读取结果,在服务器端生成相应的模板返回给客户端,最后客户端展示。
    3. 前端路由:
      其实对于前端路由来说,映射函数就是做一些 DOM 的显隐,展示出不同的页面。
    4. 前端路由的实现方案:
      • Hash
      • History
    5. Hash 的实现原理:
      URL 地址栏中 # 后面的内容,可以通过 location.hash 获取到,进而通过 hashchange 事件来监听 # 后面内容的变化;
      通过 history.length 可以看到路由总数;

      1. /**
      2. *
      3. <ul>
      4. <li><a href="#lyout1">路由1</a></li>
      5. <li><a href="#lyout2">路由2</a></li>
      6. <li><a href="#lyout3">路由3</a></li>
      7. </ul>
      8. <div id="content"></div>
      9. */
      10. class router {
      11. constructor (hash) {
      12. // hashStr 存储路由
      13. this.hashStr = hash
      14. // 初始化 watchHash 事件
      15. this.watchHash()
      16. // 给 watch 绑定监听事件,bind 改变 watchHash 方法中 this 的指向(window 变为 router)
      17. this.watch = this.watchHash.bind(this)
      18. window.addEventListener('hashchange', this.watch)
      19. }
      20. // 监听路由变化方法
      21. watchHash () {
      22. console.log('this: ', this)
      23. let hash = window.location.hash.slice(1)
      24. this.hashStr = hash
      25. if (this.hashStr) {
      26. if (this.hashStr === 'lyout1') {
      27. document.querySelector('#content').innerHTML = '路由1Content'
      28. } else if (this.hashStr === 'lyout2') {
      29. document.querySelector('#content').innerHTML = '路由2Content'
      30. } else {
      31. document.querySelector('#content').innerHTML = '路由3Content'
      32. }
      33. } else {
      34. document.querySelector('#content').innerHTML = '路由还没有开始,点击路由'
      35. }
      36. }
      37. }
      38. new router()
    6. History 的实现原理:

      在 H5 之前,只要浏览器地址栏中的 URL 地址改变,都会触发页面刷新,这个过程要消耗时间和资源。若只是两个页面某一小部分不同,进而重载页面,这无疑是一种浪费。出现 history 之后,只需要知道页面的不同部分,在原有页面重载不同部分,然后通过 History API 就可以实现在不刷新页面的情况下,变化 URL。


    History API:

    1. /*
    2. state: 需要保存的数据,此数据在触发 popstate 事件时,可以通过 event.state 获取;
    3. title: 标题,一般入参为 null;
    4. url: 设定新的历史记录的 url。新的 url 必须与当前的 url 的 origin 一直,否则会抛错。
    5. */
    6. window.history.pushState(state, title, url)
    7. window.history.replaceState(state, title, url)
    8. window.history.back()
    9. window.history.forward()
    10. window.history.go(n)

    监听:

    1. window.addEventListener('popstate', function(event) {
    2. // ...
    3. }, false)


    只是调用 pushState / replaceState 方法并不会触发该事件,只有用户点击浏览器后退,前进按钮时,或者是通过 js 调用 back / forward / go 方法时才会触发。
    如何监听 pushState / replaceState 的变化?

    1. /* 创建全局事件 */
    2. let _wr = function (type) {
    3. let orign = history[type]
    4. return function () {
    5. let rv = orign.apply(this, arguments)
    6. let e = new Event(type)
    7. e.arguments = arguments
    8. window.dispatchEvent(e)
    9. return rv
    10. }
    11. }
    12. /* 重写方法 */
    13. history.pushState = _wr('pushState')
    14. history.replace = _wr('replaceState')
    15. /* 实现监听 */
    16. window.addEventListener('pushState', function (e) {
    17. console.log('pushState')
    18. })
    19. window.addEventListener('replaceState', function (e) {
    20. console.log('replaceState')
    21. })

    参考:阿里P7:你了解路由吗?