前端路由浅析

本贴最后更新于 2023 天前,其中的信息可能已经事过景迁

前端路由浅析

很多传播活动开发过程中经常需要制作一些单页应用。基于种种不可抗原因不能使用 Vue、React 等框架进行开发,所以每次开发时都会当场制作/copy 前人的路由代码。

10 月传播活动中因为时间充裕,便自己实现了简单的路由,以后活动如果需要使用可以继续基于此进行开发。

何为路由

狭义上的路由指根据 url 变化页面也进行相应的跳变;广义上的路由指监听 url 的变化,如果 url 的值与预设值相匹配则会触发预设的回调函数。

Hash or History

Hash

hash 的原始意义指的是页面上的一个位置,比如 https://act.you.163.com/act/static/Dr5VgrU6UG.html#rfMXMkaT 这个页面的 hash 是 #rfMXMkaT,其具体位置为"办公用品",访问这个地址,浏览器就会直接定位到"办公用品"这个位置。
hash 有一个特性为 - 改变 hash 不会触发网页重载。因此可以利用这个特性对 hash 进行改变,利用 onhashchange 事件进行监听。
使用 hash 的路由一般会让页面 url 变成这样:

http://test.hduzplus.xyz/#page1
http://test.hduzplus.xyz/#page2
http://test.hduzplus.xyz/#page3

History

vue-router、React-Router 等路由框架可以使用 h5 新增的 history api 进行路由变化,监听 window 的 onpopstate 事件进行路由监听。
使用 history 的路由页面 url 会清晰的多。

http://test.hduzplus.xyz/page1
http://test.hduzplus.xyz/page2
http://test.hduzplus.xyz/page3

有一定开发基础的小伙伴可能不能理解这种路由监听方式。比如我的主页是 http://test.hduzplus.xyz/,为什么访问 http://test.hduzplus.xyz/page1 不是 404 而是进入到路由逻辑内呢?
这实际上是 history 路由方式的一个缺点。在正常情况下服务端的确会返回 404,因此我们得在服务端做处理使其返回我们想要的数据才行。具体配置方式在此不表,其配置的主要思想是将该 host 下 404 页面全部转发到 index.html 中,并由 index.html 内的 js 判断路由条件并触发相应的回调。

<!-- apache 配置demo -->
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

基于 hash 的路由实现

实现非常简单,无非就是注册对象,监听 hashchange,执行相应的函数。
选择使用 hash 方式的路由的原因是因为就活动开发而言,开发者无法直接对服务端进行配置。
实现代码如下

class Router {
  constructor(config) {
    this.config = config
    this.router = {}
    this.from = this.to = ''
    this.view()
  }

  get now() {
    return window.location.hash.substring(1)
  }

  register({
    path, beforeChange = () => {}, change = () => {}, afterChange = () => {}
  }) {
    this.router[path] = {
      beforeChange, afterChange, change
    }
  }

  go(path) {
    if (this.now === path) {
      this.render(this.router[this.now])
      return
    }
    window.location.hash = path
  }

  view() {
    this.config.forEach(item => {
      this.register(item)
    })

    window.addEventListener('hashchange', () => {
      this.render(this.router[this.now])
    })
  }

  render(obj) {
    if (typeof obj === 'undefined' || obj === null) {
      return
    }

    [this.from ,this.to] = [this.to, this.now];

    const ret = obj.beforeChange(this.from, this.to)
    if (ret === false) {
      return  
    }
    obj.change(this.from, this.to)
    obj.afterChange(this.from, this.to)
  }
}

export default Router

使用方式:

import Router from './Router'

const router = new Router([
  {
    path: 'page1',
    beforeChange: () => {},
    change: () => {},
    afterChange: () => {}
  },
  {
    path: 'page2',
    beforeChange: () => {},
    change: () => {},
    afterChange: () => {}
  },
])
  • 研究
    12 引用 • 34 回帖
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1347 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...