• 前端路由


    前端路由的两种方式:Hash和History

    Hash 模式是使用 URL 的 Hash 来模拟一个完整的 URL,因此当 URL 改变的时候页面并不会重载。History 模式则会直接改变 URL,所以在路由跳转的时候会丢失一些地址信息,在刷新或直接访问路由地址的时候会匹配不到静态资源。因此需要在服务器上配置一些信息,让服务器增加一个覆盖所有情况的候选资源,比如跳转index.html什么的,一般来说是app 依赖的页面

    Hash原理: Hash方法是在路由中带有一个#,主要原理是通过监听#后的URL路径标识符的更改而触发的浏览器hashchange事件,然后通过获取location.hash得到当前的路径标识符,再进行一些路由跳转的操作MDN

    如下:把目标路由和对应的回调记录下来,点击跳转触发 。

     1 class RouterClass {
     2   constructor() {
     3     this.isBack = false
     4     this.routes = {}        // 记录路径标识符对应的cb
     5     this.currentUrl = ''    // 记录hash只为方便执行cb
     6     this.historyStack = []  // hash栈
     7     window.addEventListener('load', () => this.render())
     8     window.addEventListener('hashchange', () => this.render())
     9   }
    10   
    11   /**
    12    * 初始化
    13    */
    14   static init() {
    15     window.Router = new RouterClass()
    16   }
    17   
    18   /**
    19    * 记录path对应cb
    20    * @param path
    21    * @param cb 回调
    22    */
    23   route(path, cb) {
    24     this.routes[path] = cb || function() {}
    25   }
    26   
    27   /**
    28    * 入栈当前hash,执行cb
    29    */
    30   render() {
    31     if (this.isBack) {      // 如果是由backoff进入,则置false之后return
    32       this.isBack = false   // 其他操作在backoff方法中已经做了
    33       return
    34     }
    35     this.currentUrl = location.hash.slice(1) || '/'
    36     this.historyStack.push(this.currentUrl)
    37     this.routes[this.currentUrl]()
    38     // console.log('refresh事件   Stack:', this.historyStack, '   currentUrl:', this.currentUrl)
    39   }
    40   
    41   /**
    42    * 路由后退
    43    */
    44   back() {
    45     this.isBack = true
    46     this.historyStack.pop()                   // 移除当前hash,回退到上一个
    47     const { length } = this.historyStack
    48     if (!length) return
    49     let prev = this.historyStack[length - 1]  // 拿到要回退到的目标hash
    50     location.hash = `#${ prev }`
    51     this.currentUrl = prev
    52     this.routes[prev]()                       // 执行对应cb
    53     // console.log('点击后退,当前stack:', this.historyStack, '   currentUrl:', this.currentUrl)
    54   }
    55 }
    56 
    57 
    58 RouterClass.init()
    59 const BtnDom = document.querySelector('button')
    60 const ContentDom = document.querySelector('.content-div')
    61 const changeContent = content => ContentDom.innerHTML = content
    62 
    63 Router.route('/', () => changeContent('默认页面'))
    64 Router.route('/page1', () => changeContent('page1页面'))
    65 Router.route('/page2', () => changeContent('page2页面'))
    66 
    67 BtnDom.addEventListener('click', Router.back.bind(Router), false)

    popstate:事件:当活动的历史记录发生变化,就会触发popstate事件,在点击浏览器的前进后退按钮或者调用上面前三个方法的时候也会触发;MDN

    • history.pushState()
    • history.popstate()
    • history.replaceState()
    • history.forward()  (history.go(1))
    • history.back()    (history.go(-1))
     1 class RouterClass {
     2   constructor(path) {
     3     this.routes = {}        // 记录路径标识符对应的cb
     4     history.replaceState({ path }, null, path)
     5     this.routes[path] && this.routes[path]()
     6     window.addEventListener('popstate', e => {
     7       console.log(e, ' --- e')
     8       const path = e.state && e.state.path
     9       this.routes[path] && this.routes[path]()
    10     })
    11   }
    12   
    13   /**
    14    * 初始化
    15    */
    16   static init() {
    17     window.Router = new RouterClass(location.pathname)
    18   }
    19   
    20   /**
    21    * 记录path对应cb
    22    * @param path 路径
    23    * @param cb 回调
    24    */
    25   route(path, cb) {
    26     this.routes[path] = cb || function() {}
    27   }
    28   
    29   /**
    30    * 触发路由对应回调
    31    * @param path
    32    */
    33   go(path) {
    34     history.pushState({ path }, null, path)
    35     this.routes[path] && this.routes[path]()
    36   }
    37 }
    38 
    39 
    40 RouterClass.init()
    41 const ul = document.querySelector('ul')
    42 const ContentDom = document.querySelector('.content-div')
    43 const changeContent = content => ContentDom.innerHTML = content
    44 
    45 Router.route('/', () => changeContent('默认页面'))
    46 Router.route('/page1', () => changeContent('page1页面'))
    47 Router.route('/page2', () => changeContent('page2页面'))
    48 
    49 ul.addEventListener('click', e => {
    50   if (e.target.tagName === 'A') {
    51     e.preventDefault()
    52     Router.go(e.target.getAttribute('href'))
    53   }
    54 })
  • 相关阅读:
    Spark源码走读6——Shuffle
    Spark源码走读5——Storage
    使用Gradle构建Android应用的渠道包
    轻松搞定面试中的二叉树题目
    QT中使用微软Speech API实现语音识别
    QT 相关资源(书籍、论坛、博客等。。。)整理...
    使用Cscope阅读大型工程Linux内核的源代码教程
    搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门
    RSA算法原理(二)
    RSA算法原理(一)
  • 原文地址:https://www.cnblogs.com/vicky24k/p/11785418.html
Copyright © 2020-2023  润新知