js web简单的路由管理器

灵感来自此博客和此库

index.html



  
    
    
    Document
  
  
    

aja-router.js

const _textIsDynamicRouteExp = /\/?:[a-zA-Z]+/;
class AjaRouter {
  _host = document.querySelector("#root");
  _routes = [];

  constructor(host) {
    if (host) this._host = host;
    this._setup();
  }

  _setup() {
    window.addEventListener("load", e => {
      this._render();
    });

    window.addEventListener("popstate", e => {
      this._render();
    });

    // window.addEventListener("hashchange", e => {
    //   console.log("hash ");
    // });
  }

  forRoot(routes = []) {
    this._routes = routes.map(route => {
      const { path } = route;
      const pathSplit = path.split("/");
      if (path && path.match(_textIsDynamicRouteExp)) {
        route.isDynamic = true;
        // 动态路由
        const params = {};
        let exp = "";
        for (var i = 0; i < pathSplit.length; i++) {
          const item = pathSplit[i];
          let expItem = "/" + item;
          if (item.startsWith(":")) {
            params[item.replace(/^:/, "")] = { index: i };
            expItem = `/(?<${item.replace(/^:/, "")}>[^/]+)`;
          }
          exp += expItem;
        }
        if (exp && exp.trim() != "") {
          exp = exp.replace(/\//, "");
        }
        route.exp = new RegExp(exp);
        route.params = params;
      }

      return route;
    });
  }

  _findHashRoute(path) {
    const hash = path ?? document.location.hash.replace(/#\/?/, "");
    return this._match(hash);
  }

  /**
   * 使用path在routes中寻找路由
   */
  _match(path) {
    // 1, 先找普通路由
    let route = this._routes.find(i => i.path === path);
    if (route) {
      return route;
    }

    // 2, 找动态路由
    route = this._routes
      .filter(i => i.isDynamic)
      .find(i => {
        const pattern = "/";
        const routeNameSplit = path.split(pattern);
        const dynamicRouteNameSplit = i.path.split(pattern);
        const equalRouteLength =
          routeNameSplit.length == dynamicRouteNameSplit.length;
        const match = path.match(i.exp);
        if (match && match.groups) {
          for (const k in match.groups) {
            const param = i.params[k];
            param.value = match.groups[k];
          }
        }

        return equalRouteLength && match;
      });

    if (route) {
      return route;
    }

    // 3, 都没找到,默认返回404路由
    return this._find404Route();
  }

  _find404Route() {
    return this._routes.find(i => i.path === "**");
  }

  _render(path) {
    const matchRoute = this._findHashRoute(path);
    if (matchRoute) {
      this._host.innerHTML = "";
      if (matchRoute.redirectTo) {
        this._render(matchRoute.redirectTo);
      } else {
        matchRoute.render(this._host, matchRoute);
      }
    }
  }

  push(path) {
    try {
      this._render(path);
      window.history.pushState({}, document.title, `#/${path}`);
    } catch (error) {}
  }
}

你可能感兴趣的:(js web简单的路由管理器)