用js徒手写一个路由框架
- 2020 年 2 月 18 日
- 筆記

分别创建 index.html 、 main.js 、router.js 和 route.js文件
route.js
export class Route { constructor(name, path, handler) { this.name = name; this.path = path; this.handler = handler; } get name() { return this._name; } set name(name) { this._name = name; } get path() { return this._path; } set path(path) { this._path = path; } get handler() { return this._handler; } set handler(handler) { this._handler = handler; } }
router.js
import { Route } from './route.js' export class Router { constructor() { this.mode = 'history' this.routes = [] this.root = '/' } get root() { return this._root; } set root(val) { this._root = val; } get mode() { return this._mode } set mode(val) { this._mode = (val == 'history' && window.history.pushState) ? 'history' : 'hash' } get routes() { return this._routes; } set routes(val) { this._routes = val; } add(route) { this.routes.push(new Route(route.name, route.path, route.handler)) return this } navigate(route) { route = route ? route : '' this.match(route) } match(route) { for (var i = 0; i < this.routes.length; i++) { let paramNames = [] let regexPath = this.routes[i].path.replace(/([:*])(w+) /g, function (full, colon, name) { paramNames.push(name) return '([^/]+)'; }) + '(?:/|$)' let routeMatch = route.match(new RegExp(regexPath)); if (routeMatch !== null) { var params = routeMatch .slice(1, routeMatch.length) .reduce((params, value, index) => { if (params === null) params = {}; params[paramNames[index]] = value; return params; }, null); if (params === null) { this.routes[i].handler() } else { this.routes[i].handler(params) } this.location(route) } } } location(route) { if (this.mode === 'history') { window.history.pushState(null, null, this.root + route) } else { route = route.replace(/^//, '').replace(//$/, '') window.kk = window.kk.replace(/#(.*)$/, '') + '#' + route } } }
main.js
import { Router } from './router.js' const router = new Router() router.mode = 'hash' router.root = 'http://192.168.1.103:8080' router.add({ name: 'home', path: '/home', handler: () => console.log('handler to home') }) router.add({ name: 'about', path: '/about', handler: () => console.log('handler to about') }) router.add({ name: 'contact', path: '/contact', handler: () => console.log('handler to contact') }) router.add({ name: 'user', path: '/user/:id/:action', handler: (params) => console.log('user handler params') }) const activeRoutes = Array.from(document.querySelectorAll('[route]')) activeRoutes.forEach((route) => route.addEventListener('click', (e) => { e.preventDefault(); router.navigate(e.target.getAttribute('route')) }, false))
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Router</title> <script type="module" src="main.js"></script> </head> <body> <h3>Router</h3> <div id="view"></div> <button route="/"> Root</button> <button route="/about">About</button> <button route="/contact">Contact</button> <button route="404">404</button> <button route="/user/24/save">User add</button> </body> </html>
源码地址 https://github.com/lilugirl/handmade_router