好家伙,

 

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

 

1.替换router

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

 

2.大致结构

let Vue; // 保存vue的构造函数
class VueRouter {
constructor(options) { }
} VueRouter.install = (_Vue) => {
Vue = _Vue; //备份Vue Vue.mixin({
beforeCreate() {
if (this.$options.router) {
Vue.prototype.$router = this.$options.router;
}
}
})
Vue.component("router-link", {}); //实现思路,找到对应的组件并将它渲染出来
Vue.component("router-view", {}); } export default VueRouter;

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

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

3.router-link实现

  3.1.组件的使用

 

  3.2.实现

Vue.component("router-link", {
props: {
to: {
type: String,
required: true,
},
},
render(h) {
return h("a", {
attrs: {
href: `#${this.to}`
}
}, this.$slots.default);
}
});

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

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

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

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

4.实现router-view

Vue.component("router-view", {
render(h) {
let component = null;
//获取当前路由所对应的组件并将它渲染出来
const current = this.$router.current;
const route = this.$router.$options.routes.find((route) =>
route.path === current
)
// const route = this.$router.$options.routes.find((route) =>
// {route.path === current}
// )
//!!错误
//若使用箭头函数块{},必须要有返回值 console.log(route, current)
if (route) {
component = route.component
} return h(component);
}
});

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

5.实现VueRouter

class VueRouter {
constructor(options) {
this.$options = options; this.current = "/"; let initial = window.location.hash.slice(1) || "/" Vue.util.defineReactive(this, "current", initial) window.addEventListener("hashchange", () => {
this.current = window.location.hash.slice(1) || "/"
console.log(this.current)
})
}
}

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

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

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

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

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

搞定

6.源码

let Vue; // 保存vue的构造函数
class VueRouter {
constructor(options) {
this.$options = options; this.current = "/"; let initial = window.location.hash.slice(1) || "/" Vue.util.defineReactive(this, "current", initial) window.addEventListener("hashchange", () => {
this.current = window.location.hash.slice(1) || "/"
console.log(this.current)
})
}
} VueRouter.install = (_Vue) => {
Vue = _Vue; //备份Vue Vue.mixin({
beforeCreate() {
if (this.$options.router) {
Vue.prototype.$router = this.$options.router;
}
}
})
Vue.component("router-link", {
props: {
to: {
type: String,
required: true,
},
},
render(h) {
return h("a", {
attrs: {
href: `#${this.to}`
}
}, this.$slots.default);
}
}); //实现思路,找到对应的组件并将它渲染出来
Vue.component("router-view", {
render(h) {
let component = null;
//获取当前路由所对应的组件并将它渲染出来
const current = this.$router.current;
// const route = this.$router.$options.routes.find((route) =>
// route.path === current
// )
const route = this.$router.$options.routes.find((route) =>
{return route.path === current}
)
//!!错误
//若使用箭头函数块{},必须要有返回值 console.log(route, current)
if (route) {
component = route.component
} return h(component);
}
}); } export default VueRouter;

7.补充

一个小小bug

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

不能写成

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

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

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

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

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

第143篇:手写vue-router,实现router-view的更多相关文章

  1. 手写 Vue 系列 之 Vue1.x

    前言 前面我们用 12 篇文章详细讲解了 Vue2 的框架源码.接下来我们就开始手写 Vue 系列,写一个自己的 Vue 框架,用最简单的代码实现 Vue 的核心功能,进一步理解 Vue 核心原理. ...

  2. 剖析手写Vue,你也可以手写一个MVVM框架

    剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...

  3. 手写 Vue 系列 之 从 Vue1 升级到 Vue2

    前言 上一篇文章 手写 Vue 系列 之 Vue1.x 带大家从零开始实现了 Vue1 的核心原理,包括如下功能: 数据响应式拦截 普通对象 数组 数据响应式更新 依赖收集 Dep Watcher 编 ...

  4. iOS开发UI篇—手写控件,frame,center和bounds属性

    iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...

  5. iOS开发基础篇-手写控件

    一.手写控件的步骤 1)使用相应的控件类创建控件对象: 2)设置该控件的各种属性: 3)添加空间到视图中: 4)如果是 UIButton 等控件,还需考虑控件的单击事件等: 二.添加 UIButton ...

  6. 手写vue路由

    目录 一.简易demo 二.Vue-Router传参方式 三.进阶-路由导航 一.简易demo // routes注册 import Vue from "vue"; // impo ...

  7. 手写vue中v-bind:style效果的自定义指令

    自定义指令 什么是自定义指令 以 v- 为前缀,然后加上自己定义好的名字组成的一个指令就是自定义指令.为什么要有自定义指令呢?在有些时候,你仍然需要对普通的DOM元素进行底层的操作,这个时候就可以用到 ...

  8. 手写vue双向绑定数据

    来一张原理图: 实现思路: (1)绑定data 种的数据,为每个数据添加指令.通过Object,defineProperty() 来通知属性是否更改 (2) 找到每个DOM节点的指令.绑定事件.并绑定 ...

  9. 学习手写vue,理解原理

    class Compiler{ constructor(el,vm){ // 判断el属性 是不是 一个元素, 如果不是就获取 this.el = this.isElementNode(el)?el: ...

  10. 手写vue observe数据劫持

    实现代码: class Vue { constructor(options) { //缓存参数 this.$options = options; //需要监听的数据 this.$data = opti ...

随机推荐

  1. ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑

    ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑 1.Elasticsearch 产生背景 大规模数据如何检索 如:当系统数据量上了 10 亿.100 亿条的时 ...

  2. Origin2017、Origin2018详细安装教程

    1.Origin2017安装 1.1 安装步骤: 解压安装包,打开"Origin2017"目录,双击"setup.exe"开始安装 安装步骤1,点击[下一步] ...

  3. Dash 2.15版本新特性介绍

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,Dash不久前发布了其2.15.0版本,新增了一些实用的特性 ...

  4. 【C语言进阶】【小项目】实现一个通讯录【C语言知识点汇总项目】通过这个项目,掌握C语言重要知识点

    [C语言进阶][小项目]实现一个通讯录[C语言知识点汇总项目]通过这个项目,掌握C语言重要知识点 欢迎来到#西城s的博客,今天,博主带着大家用C实现一个通讯录!干货满满不要错过噢! 作者: #西城s ...

  5. 十八张图带你入门实时监控系统HertzBeat

    我们经常讲:研发人员有两只眼睛,一只是监控平台,另一只是日志平台.在对性能和高可用讲究的场景里,监控平台的重要性再怎么强调也不过分. 这篇文章,我们聊聊开源实时监控告警系统 HertzBeat 赫兹跳 ...

  6. 21.2 静态TLS--《Windows核心编程》

    部分笔记来自于:https://blog.csdn.net/Steven_programe_life/article/details/103358251?utm_medium=distribute.p ...

  7. 《ASP.NET Core 微服务实战》-- 读书笔记(第8章)

    第 8 章 服务发现 面对大量服务,为了简化配置和管理工作,我们需要了解"服务发现"概念 回顾云原生特性 配置外置 将 URL 和登录凭证移到配置文件和 C# 代码之外,放到环境变 ...

  8. Python-pymysql操作MySQL数据库

    一.安装pymysql py -m pip install pymysql; 二.pymysql数据库操作 1.简单示例 #coding=utf-8 import pymysql ## 打开数据库连接 ...

  9. MySQL优化技术系列-谓词下推(pushdown)

    谓词下推 将外层查询块的 WHERE 子句中的谓词移入所包含的较低层查询块(例如视图),从而能够提早进行数据过滤以及有可能更好地利用索引. 这在分区数据库环境中甚至更为重要,其原因在于,提早进行过滤有 ...

  10. Python 爬虫方法总结

    实现爬虫的套路 准备URL 准备start_url url地址规律不明显,总数不确定 通过代码提取下一页的url 通过xpath提取 寻找url地址,部分参数在当前的响应中(比如当前页码数和总页码数在 ...