zoukankan      html  css  js  c++  java
  • 前端路由

    前端路由的两种方式: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 })
  • 相关阅读:
    Java 的垃圾回收机制
    Java 变参函数的实现
    对已知有限集合中缺失或重复元素的查找
    Java 旋转数组查找旋转点和任意元素(元素可重复)
    第三章 磁盘分区
    第二章 一切都是对象
    发布 AutoRssReceiver Console 机器人! 兼讲: .Net 中的 Attribute (特性)
    .Net/C#/VB/TSQL/Java 实现: 将天文数字转换成中文大写 (2000 年前的思路,打劫的,一点儿技术含量都没有)
    .Net/C#/VB/TSQL/Java/Script 实现: 将天文数字转换成中文大写 (2000 年前的思路,打劫的,一点儿技术含量都没有)
    利用"委托"实现类的对象实例按"多字段嵌套"排序
  • 原文地址:https://www.cnblogs.com/vicky24k/p/11785418.html
Copyright © 2011-2022 走看看