实现一个 Vue-Router,需要考虑的问题有哪些?
- 如何将状态和路由记录同步
 
- 如何通过判断路由记录决定渲染哪个视图
 
- 如何处理更新问题
 
BrowserHistory,原生 API 可以监听路有变化?
实现一个 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, 并展示出来.