Skip to main content

路由

BrowserRouter(History)

使用干净的 URL 将当前位置存储在浏览器的地址栏中,并使用浏览器的内置历史栈的 api 进行导航。

History 路由则是通过调用浏览器提供的 history API 实现页面的前进和后退操作

通过 window.onpopstate 监听路由变化

但是不能监听到 pushState 和 replaceState 的变化

会对这两个方法进行重写

当使用 this.$router.replace 和this.$router.push 时

我们会分别调用重写的这两种方法

实现

使用 history.replaceState, history.pushState 修改历史记录 监听 popstate 事件,拿到 path *** 从而手动跳转

// 定义 Router
class Router {
constructor() {
this.routes = {};
this.listerPopState();
}

init(path) {
history.replaceState({ path: path }, null, path);
this.routes[path] && this.routes[path]();
}

route(path, callback) {
this.routes[path] = callback;
}

push(path) {
history.pushState({ path: path }, null, path);
this.routes[path] && this.routes[path]();
}

listerPopState() {
window.addEventListener("popstate", (e) => {
const path = e.state && e.state.path;
this.routers[path] && this.routers[path]();
});
}
}

// 使用 Router

window.miniRouter = new Router();
miniRouter.route("/", () => console.log("page1"));
miniRouter.route("/page2", () => console.log("page2"));

// 跳转
miniRouter.push("/page2"); // page2

HashRouter

HashRouter 用于当 URL 由于某种原因不应(或不能)发送到服务器时, 在 Web 浏览器中使用。在某些您无法完全控制服务器的共享托管场景中,可能会发生这种情况。在这些情况下,HashRouter 可以将当前位置存储在 hash 当前 URL 的部分中,因此永远不会将其发送到服务器。

强烈建议您不要使用HashRouter,除非绝对必要。

hash 模式背后的原理是 onhashchange 事件,可以在 window 对象上监听这个事件 由于第一次需要加载,所以也要监听 load 事件

window.onhashchange = function (event) {
console.log(event.oldURL, event.newURL);
let hash = location.hash.slice(1); // 去掉#
document.body.style.color = hash;
};

然后去读 location.hash 执行操作

实现

// 定义 Router
class Router {
constructor() {
this.routes = {}; // 存放路由path及callback
this.currentUrl = "";

// 监听路由change调用相对应的路由回调
window.addEventListener("load", this.refresh, false);
window.addEventListener("hashchange", this.refresh, false);
}

route(path, callback) {
this.routes[path] = callback;
}

push(path) {
this.routes[path] && this.routes[path]();
}
}

// 使用 router
window.miniRouter = new Router();
miniRouter.route("/", () => console.log("page1"));
miniRouter.route("/page2", () => console.log("page2"));

miniRouter.push("/"); // page1
miniRouter.push("/page2"); // page2

MemoryRouter

MemoryRouter将其内部位置存储在数组中,它不依赖于外部源,例如浏览器中的历史堆栈。这使得它非常适合需要完全控制历史堆栈的场景,例如测试。

大多数 React Router 的测试都是使用 MemoryRouter编写的,