首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用js徒手写一个路由框架

用js徒手写一个路由框架

作者头像
lilugirl
发布2020-02-18 13:24:51
6560
发布2020-02-18 13:24:51
举报
文章被收录于专栏:前端导学前端导学

分别创建 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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档