第143篇:手写vue-router,实现router-view
好家伙,
今天来手写我们的老伙计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的更多相关文章
- 手写 Vue 系列 之 Vue1.x
前言 前面我们用 12 篇文章详细讲解了 Vue2 的框架源码.接下来我们就开始手写 Vue 系列,写一个自己的 Vue 框架,用最简单的代码实现 Vue 的核心功能,进一步理解 Vue 核心原理. ...
- 剖析手写Vue,你也可以手写一个MVVM框架
剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...
- 手写 Vue 系列 之 从 Vue1 升级到 Vue2
前言 上一篇文章 手写 Vue 系列 之 Vue1.x 带大家从零开始实现了 Vue1 的核心原理,包括如下功能: 数据响应式拦截 普通对象 数组 数据响应式更新 依赖收集 Dep Watcher 编 ...
- iOS开发UI篇—手写控件,frame,center和bounds属性
iOS开发UI基础—手写控件,frame,center和bounds属性 一.手写控件 1.手写控件的步骤 (1)使用相应的控件类创建控件对象 (2)设置该控件的各种属性 (3)添加控件到视图中 (4 ...
- iOS开发基础篇-手写控件
一.手写控件的步骤 1)使用相应的控件类创建控件对象: 2)设置该控件的各种属性: 3)添加空间到视图中: 4)如果是 UIButton 等控件,还需考虑控件的单击事件等: 二.添加 UIButton ...
- 手写vue路由
目录 一.简易demo 二.Vue-Router传参方式 三.进阶-路由导航 一.简易demo // routes注册 import Vue from "vue"; // impo ...
- 手写vue中v-bind:style效果的自定义指令
自定义指令 什么是自定义指令 以 v- 为前缀,然后加上自己定义好的名字组成的一个指令就是自定义指令.为什么要有自定义指令呢?在有些时候,你仍然需要对普通的DOM元素进行底层的操作,这个时候就可以用到 ...
- 手写vue双向绑定数据
来一张原理图: 实现思路: (1)绑定data 种的数据,为每个数据添加指令.通过Object,defineProperty() 来通知属性是否更改 (2) 找到每个DOM节点的指令.绑定事件.并绑定 ...
- 学习手写vue,理解原理
class Compiler{ constructor(el,vm){ // 判断el属性 是不是 一个元素, 如果不是就获取 this.el = this.isElementNode(el)?el: ...
- 手写vue observe数据劫持
实现代码: class Vue { constructor(options) { //缓存参数 this.$options = options; //需要监听的数据 this.$data = opti ...
随机推荐
- FaceFusion:探索无限创意,创造独一无二的面孔融合艺术!
FaceFusion:探索无限创意,创造独一无二的面孔融合艺术! 它使用先进的图像处理技术,允许用户将不同的面部特征融合在一起,创造有趣和令人印象深刻的效果.这个项目的潜在应用包括娱乐.虚拟化妆和艺术 ...
- 【一】分布式训练---单机多卡多机多卡(飞桨paddle1.8)
1.分布式训练简介 分布式训练的核心目的: 加快模型的训练速度.通过对训练任务按照一定方法拆分分配到多个计算节点进行计算,再按照一定的方法对需要汇总的信息进行聚合,从而实现加快训练速度的目的. 1.1 ...
- 深度学习应用篇-计算机视觉-语义分割综述[5]:FCN、SegNet、Deeplab等分割算法、常用二维三维半立体数据集汇总、前景展望等
深度学习应用篇-计算机视觉-语义分割综述[5]:FCN.SegNet.Deeplab等分割算法.常用二维三维半立体数据集汇总.前景展望等 语义分割综述(semantic segmentation) 1 ...
- 补发一篇tensorflow下MADDPG环境搭建配置
相关文章: [一]MADDPG-单智能体|多智能体总结(理论.算法) [二]MADDPG多智能体算法实现(parl)[追逐游戏复现] 之前用的都是paddle,现在补一下tf的. github上ope ...
- PaddleHub--飞桨预训练模型应用工具{风格迁移模型、词法分析情感分析、Fine-tune API微调}【一】
相关文章: 基础知识介绍: [一]ERNIE:飞桨开源开发套件,入门学习,看看行业顶尖持续学习语义理解框架,如何取得世界多个实战的SOTA效果?_汀.的博客-CSDN博客_ernie模型 百度飞桨:E ...
- NFS实现部署Linux文件共享
NFS 即网络文件系统,是一种使用于分布式文件系统的协议,由Sun公司开发,于1984年向外公布,功能是通过网络让不同的机器,不同的操作系统能够彼此分享各自的数据,让应用程序在客户端通过网络访问位于服 ...
- 算法与数据结构-07-手写类HashTable
package day05; import java.sql.SQLOutput; import java.util.Scanner; /** * 哈希表代码实现 */ public class Ha ...
- 认识3D模型-GLTF文件
GLTF文件格式 glTF的全称(Graphics Language Transmission Format)图形语言传输格式.是三维场景和模型的标准文件格式. glTF 核心是 JSON 文件,描述 ...
- 苹果iOS 17正式版来了:iPhone X/8系列等机型无缘
据媒体报道,苹果会在9月13日凌晨1点发布iPhone 15系列新品,该机出厂预装iOS 17正式版系统. 在iPhone 15系列之后,苹果会向老机型推送iOS 17正式版更新.据爆料,苹果将会在9 ...
- 程序员必备技能:一键创建windows 服务
使用windows开发或者使用windows服务器的朋,应该经常会遇到有些程序要开机启动,或者有些服务要持续执行. 这样最稳定可靠的,就是把程序创建为windows服务. 以下bat脚本,仅供参考. ...