router 的简易实现

基于 hash 的实现

以下为 hashChange 的简版实现

class Router {
  constructor() {
    this.router = {}
    window.addEventListener('hashchange', (e) => {
      const tag = location.hash.slice(1)
      this.router[tag] && this.router[tag]()
    })
  }

  route(path, fn) {
    this.router[path] = fn
  }
}

const router = new Router()
const changeColor = (color) => {
  document.body.style.background = color
}
router.route('red', () => { changeColor('red') })
router.route('yellow', () => { changeColor('yellow') })
router.route('blue', () => { changeColor('blue') })
<ul>
  <a href="#red">red</a>
  <a href="#yellow">yellow</a>
  <a href="#blue">blue</a>
</ul>

基于 history 的实现

以下代码需要运行在 http 端口。

class Router {
  constructor() {
    this.router = {}
    window.addEventListener('popstate', (e) => {
      const path = e.state.path
      this.router[path] && this.router[path]()
    })
  }

  route(path, fn) {
    this.router[path] = fn
  }

  go(path) {
    history.pushState({ path: path }, null, path) // 核心思路, pushState 进去的第一个对象会在点击回退/前进按钮时触发 popstate
    this.router[path] && this.router[path]()
  }
}

const router = new Router()
const changeColor = (color) => {
  document.body.style.background = color
}
router.route('red', () => { changeColor('red') })
router.route('yellow', () => { changeColor('yellow') })
router.route('blue', () => { changeColor('blue') })
document.getElementsByTagName('ul')[0].addEventListener('click', (e) => {
  router.go(e.target.innerText)
})
<ul>
  <li href="red">red</li>
  <li href="yellow">yellow</li>
  <li href="blue">blue</li>
</ul>

路由的监听

  • hash 路由

window.addEventListener('hashchange')

  • history 路由

参考

面试官: 你了解前端路由吗?