经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
第143篇:手写vue-router,实现router-view
来源:cnblogs  作者:养肥胖虎  时间:2024/3/13 9:17:37  对本文有异议

好家伙,

 

今天来手写我们的老伙计vue-router,

 

1.替换router

新开一个项目,并使用我们手写的router

 

2.大致结构

  1. let Vue; // 保存vue的构造函数
  2. class VueRouter {
  3. constructor(options) {
  4. }
  5. }
  6. VueRouter.install = (_Vue) => {
  7. Vue = _Vue; //备份Vue
  8. Vue.mixin({
  9. beforeCreate() {
  10. if (this.$options.router) {
  11. Vue.prototype.$router = this.$options.router;
  12. }
  13. }
  14. })
  15. Vue.component("router-link", {});
  16. //实现思路,找到对应的组件并将它渲染出来
  17. Vue.component("router-view", {});
  18. }
  19. export default VueRouter;

  2.1.这里使用Vue.mixin(),使任何组件都能调用到router

  2.2.Vue = _Vue,一会要用到Vue的方法,将某个变量变为响应式的

 

 

 

3.router-link实现

  3.1.组件的使用

 

  3.2.实现

  1. Vue.component("router-link", {
  2. props: {
  3. to: {
  4. type: String,
  5. required: true,
  6. },
  7. },
  8. render(h) {
  9. return h("a", {
  10. attrs: {
  11. href: `#${this.to}`
  12. }
  13. }, this.$slots.default);
  14. }
  15. });

  重点来了,为什么要用个#?

  在这段代码中,使用 # 的目的是为了在单页面应用(SPA)中实现基于 hash 的路由。在传统的单页面应用中,通过改变 URL 中的 hash   部分来切换页面内容,而不会导致整个页面重新加载。这种方式被称为 hash 模式路由。

  具体来说,当用户点击带有 # 的链接时,浏览器会更新 URL 中的 hash 部分,但不会触发整个页面的重新加载,而是根据新的 hash 值来  更新页面内容,从而实现页面的切换和路由导航。

  在 Vue 中,使用 # 可以帮助我们正确地处理 hash 模式路由。

 

4.实现router-view

  1. Vue.component("router-view", {
  2. render(h) {
  3. let component = null;
  4. //获取当前路由所对应的组件并将它渲染出来
  5. const current = this.$router.current;
  6. const route = this.$router.$options.routes.find((route) =>
  7. route.path === current
  8. )
  9. // const route = this.$router.$options.routes.find((route) =>
  10. // {route.path === current}
  11. // )
  12. //!!错误
  13. //若使用箭头函数块{},必须要有返回值
  14. console.log(route, current)
  15. if (route) {
  16. component = route.component
  17. }
  18. return h(component);
  19. }
  20. });

  总体上看,代码逻辑非常简单,在router中找到匹配的组件,然后返回相应的组件就好了,但问题来了,我怎么知道当前页面current是什么?

 

5.实现VueRouter

  1. class VueRouter {
  2. constructor(options) {
  3. this.$options = options;
  4. this.current = "/";
  5. let initial = window.location.hash.slice(1) || "/"
  6. Vue.util.defineReactive(this, "current", initial)
  7. window.addEventListener("hashchange", () => {
  8. this.current = window.location.hash.slice(1) || "/"
  9. console.log(this.current)
  10. })
  11. }
  12. }

     第一步:开始我们默认this.current = "/"; 即首页,

  第二步:将current变为响应式数据,

  第三步:让current动态获取当前路由的值

问:为什么要将current变为响应式数据?

答:render的更新依赖于响应式数据curren,若current不为响应式数据,current变化,render不会重新渲染

 

搞定

 

6.源码

  1. let Vue; // 保存vue的构造函数
  2. class VueRouter {
  3. constructor(options) {
  4. this.$options = options;
  5. this.current = "/";
  6. let initial = window.location.hash.slice(1) || "/"
  7. Vue.util.defineReactive(this, "current", initial)
  8. window.addEventListener("hashchange", () => {
  9. this.current = window.location.hash.slice(1) || "/"
  10. console.log(this.current)
  11. })
  12. }
  13. }
  14. VueRouter.install = (_Vue) => {
  15. Vue = _Vue; //备份Vue
  16. Vue.mixin({
  17. beforeCreate() {
  18. if (this.$options.router) {
  19. Vue.prototype.$router = this.$options.router;
  20. }
  21. }
  22. })
  23. Vue.component("router-link", {
  24. props: {
  25. to: {
  26. type: String,
  27. required: true,
  28. },
  29. },
  30. render(h) {
  31. return h("a", {
  32. attrs: {
  33. href: `#${this.to}`
  34. }
  35. }, this.$slots.default);
  36. }
  37. });
  38. //实现思路,找到对应的组件并将它渲染出来
  39. Vue.component("router-view", {
  40. render(h) {
  41. let component = null;
  42. //获取当前路由所对应的组件并将它渲染出来
  43. const current = this.$router.current;
  44. // const route = this.$router.$options.routes.find((route) =>
  45. // route.path === current
  46. // )
  47. const route = this.$router.$options.routes.find((route) =>
  48. {return route.path === current}
  49. )
  50. //!!错误
  51. //若使用箭头函数块{},必须要有返回值
  52. console.log(route, current)
  53. if (route) {
  54. component = route.component
  55. }
  56. return h(component);
  57. }
  58. });
  59. }
  60. export default VueRouter;

 

 

7.补充

一个小小bug

  1. const route = this.$router.$options.routes.find((route) =>
  2. route.path === current
  3. )

不能写成

  1. const route = this.$router.$options.routes.find((route) =>
  2. {route.path === current}
  3. )

第一段代码使用了简洁的箭头函数写法,直接返回了 route.path === current 的结果。这种写法适用于只有一行代码的情况,箭头函数会自动将这一行代码的结果作为返回值。因此,第一段代码会返回第一个满足条件 route.path === current 的 route 对象。

第二段代码使用了代码块 {} 包裹起来,但在代码块中没有显式返回值。这种情况下,箭头函数不会自动返回代码块中的结果,需要手动添加 return 关键字来返回值。因此,第二段代码中的箭头函数没有正确返回值,会导致代码出错。

所以,若要使用代码块 {}

  1. const route = this.$router.$options.routes.find((route) =>
  2. {return route.path === current}
  3. )

 

原文链接:https://www.cnblogs.com/FatTiger4399/p/18068833

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号