实现一个 hash 路由
HTML 部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <div class="header"> <div> <a href="#">首页</a> </div> <div> <a href="#about">关于</a> </div> <div><a href="#me">我的</a></div> <div onclick="window.history.go(-1)">返回</div> </div> </body> <style> .header { background-color: black; height: 100px; line-height: 100px; display: flex; color: #fff; justify-content: space-around; } a:link, a:hover, a:active, a:visited { color: #fff; text-decoration: none; } </style> <script src="./hashroutes.js"></script> </html>
|
JS 部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class Route { constructor() { console.log(this); this.routes = {}; this.refresh = this.refresh.bind(this); window.addEventListener("load", this.refresh); window.addEventListener("hashchange", this.refresh); }
route(path, callback) { this.routes[path] = callback || function () {}; }
refresh() { console.log(this); let path = `/${window.location.hash.slice(1) || ""}`; console.log(path); let cb = this.routes[path]; cb && cb(); } }
let Router = new Route(); let body = document.querySelector("body"); Router.route("/", function (res) { body.style.backgroundColor = "red"; });
Router.route("/about", function () { body.style.backgroundColor = "blue"; });
Router.route("/me", function () { body.style.backgroundColor = "green"; });
|
实现一个 history 路由
hash 虽然能解决问题,但是带有#不太美观。
方法
- window.history.back()
- window.history.forward()
- window.history.go(number)
- window.history.pushState() 新增=》A B =》 A B C
- window.history.replaceState() 覆盖/替换 A B =》 A C
- history 模式下可以使用 Popstate 事件来监听 url 的变化
- pushState 和 replaceState 并不会触发 Popstate 事件
- 哪些情况会触发 popstate 呢?
- 浏览器的前进/后退按钮
- history/back/forward/go
参数
- state:是一个对象,是一个指定网址相关的状态对象,如果不需要,可以为 null
- title:新页面的标题,null
- URL:新的网址,必须与当前页面出于同一个域,才会显示
部署 history 路由的时候,要使你的路由中的所有 path 都访问到 index.html 文件
HTML 部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <!DOCTYPE html> <html lang="en"> <body> <div class="header"> <div> <a href="/gray">灰色</a> </div> <div> <a href="/green">绿色</a> </div> <div><a href="/">白色</a></div> <div onclick="window.history.go(-1)">返回</div> </div> </body> <style> .header { background-color: black; height: 100px; line-height: 100px; display: flex; color: #fff; justify-content: space-around; } a:link, a:hover, a:active, a:visited { color: #fff; text-decoration: none; } </style> <script src="./hashroutes.js"></script> </html>
|
JS 部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| class Route { constructor() { this.routes = {}; this.bindPopState(); }
route(path, callback) { this.routes[path] = callback || function () {}; }
init(path) { window.history.replaceState({ path }, null, path); this.execCallbackByPath(path); }
bindPopState() { window.addEventListener("popstate", (e) => { const path = e.state && e.state.path; console.log(path); this.execCallbackByPath(path); }); }
go(path) { window.history.pushState( { path, }, null, path ); this.execCallbackByPath(path); }
execCallbackByPath(path) { const cb = this.routes[path]; if (cb) { cb(); } } }
let Router = new Route(); let body = document.querySelector("body"); Router.route("/", function (res) { body.style.backgroundColor = "red"; });
Router.route("/about", function () { body.style.backgroundColor = "blue"; });
Router.route("/me", function () { body.style.backgroundColor = "green"; });
|
VueRouter
- vue router 从列表浏览了一段时间,点击进了一个详情页,然后返回的时候,我期望回到列表页还是停留在原来的浏览位置,你可以怎么做?
- keep-alive
- localStorage/sessionStorage + scrollTop + scrollTo
- scrollBehavior
- router-view 是什么?
类似于动态的组件.
找到当前路径对应的 component, 并展示出来.