好家伙,

 

0.什么是路由?

路由就是匹配到对应路径显示对应的组件!

那么我们要如何去实现?

我们来回忆一下这router怎么用的

1. 声明式路由配置:在路由配置对象中,定义路径与组件的映射关系。例如:
import AboutComponent from '../views/AboutComponent.vue'

const routes = [
{ path: '/', component: HomeComponent },
{ path: '/about', component: AboutComponent },
{ path: '/user/:id', component: UserComponent },
];
2. 安装路由插件:在 Vue 根实例中,使用 `Vue.use()` 方法安装 vue-router 插件,
并将路由实例注入到根实例中。
import Vue from 'vue';
import VueRouter from 'vue-router'; Vue.use(VueRouter);
3. 创建 router 实例:根据路由配置对象创建一个 VueRouter 实例。
const router = new VueRouter({
routes,
mode: 'history',
base: '',
});
4. 挂载路由:将创建的 router 实例挂载到 Vue 应用上。
new Vue({
router,
render: (h) => h(App),
}).mount('#app');
5. 在组件中使用 `<router-view>`:在需要显示路由组件的页面中,
使用 `<router-view>` 标签。该标签会根据当前路由自动渲染对应的组件。
<template>
<div>
<router-link to="/about">about</router-link>
<router-view></router-view>
</div>
</template>

6. 导航:通过调用 router 实例的方法(如 `router.push()`)实现页面跳转。当用户访问不同的路径时,vue-router 会根据路由配置自动渲染对应的组件。


图例:

 也就是说如果我点击了about,就对应跳到/about,并在下方展示这个路径对应的组件

于是我们目标明确了,事实上,我们只需要解决三个问题

1.router-link的实现

2.router-view的实现

3.路径到组件的映射关系的实现

 目录结构如下:

1.router-link的实现

routerLink.jsx

  //组件
export default{
props:{ //组件的属性
to:{
type:String,
required:true
},
tag:{
type:String
}
}, //jsx
render(){
let tag = this.tag || 'a'
//跳转
console.log(tag,666)
let handler = ()=>{
this.$router.push(this.to)
}
return <tag onclick={handler}>{this.$slots.default}</tag >//jsx {变量}
}
}

2.router-view的实现

routerView.js

export default {
functional: true,
// 函数式组件
render(h, { parent, data }) { // 1 h 2 属性
//1 获取到组件
let route = parent.$route // 获取到route
// this match component
// 2问题 嵌套 /about/a :[about, a] routerView
data.routerView = true
let depath = 0
while (parent) {
// $vnode 相当于一个 占位符
if (parent.$vnode && parent.$vnode.data.routerView) {
depath++
}
parent = parent.$parent //一直寻找父亲
}
let recode = route.metched[0].metched[depath] if (!recode) {
return h() // 空
}
return h(recode.component, data)
}
}

3.路径到组件的映射关系的实现

index.js

export default class VueRouter {
constructor(options = {}) {
// vue-router 核心 1 match核心 [{},{}] => {'/':{组件相关信息},'/about':{}}
console.log(options.routes,'this is options.routes')
this.match = createMatch(options.routes || [])
this.beforeHooks= []
// 核心二:浏览器路由管理
// 1;获取模式
options.mode = options.mode || 'hash'
//进行判断
switch (options.mode) {
case 'hash':
this.history = new HashHistory(this)
break;
case 'history':
this.history = new HtmlHistory(this)
break
}
console.log(this.history)
}

createMatch.js

export function createMatch(routes) { //匹配器
//1变成一个路由映射表 [{},{}] => {'/':{组件相关信息},'/about':{},/about/c:{}}
const pathMap = createRouterMap(routes)
//2addRoutes 动态添加路由
// addRoutes(routes)
function addRoutes(routes) { // 1:用户自己动态的路由 2
// 注意需要合并在一起 createRouterMap(routes, pathMap)
} /.
.
.
./
}

createRouterMap.js

`createRouterMap` 函数用于创建路径映射对象
export function createRouterMap(routes,routerOptions={}) {
// console.log(routes,5556)
let pathMap = routerOptions
routes.forEach(router => {
//[{path:'/},{}] => {'/':{组件相关信息},'/about':{},/about/a:{}}
console.log(router, pathMap,'||this is router, pathMap')
addRouterRecode(router, pathMap)
})
// console.log(pathMap)
//问题 路由嵌套 /about/a
return pathMap
} function addRouterRecode(router, pathMap,parent) {
// 1路径 / 记录 let path = parent ?`${parent.path}/${router.path}`:router.path
let recode = {
path: router.path,
name: router.name,
component: router.component,
parent
}
//添加
if (!pathMap[path]) {
pathMap[path] = recode
}
//有没有儿子
if(router.children){
//递归
router.children.forEach(child=>{
//注意 parent
addRouterRecode(child, pathMap,recode)
})
}
}

对于以上createRouterMap方法,举个例子
const routes = [
{
path: '/',
name: 'Home',
component: HomeComponent
},
{
path: '/about',
name: 'About',
component: AboutComponent,
children: [
{
path: 'contact',
name: 'Contact',
component: ContactComponent
}
]
}
]; const routerOptions = {
base: '/'
}; const pathMap = createRouterMap(routes, routerOptions); 得到结果 {
'/': {
path: '/',
name: 'Home',
component: HomeComponent,
parent: null
},
'/about': {
path: '/about',
name: 'About',
component: AboutComponent,
parent: '/'
},
'/about/contact': {
path: '/about/contact',
name: 'Contact',
component: ContactComponent,
parent: '/about'
}
}


Vue源码学习(十九):router基本原理的更多相关文章

  1. Vue源码学习1——Vue构造函数

    Vue源码学习1--Vue构造函数 这是我第一次正式阅读大型框架源码,刚开始的时候完全不知道该如何入手.Vue源码clone下来之后这么多文件夹,Vue的这么多方法和概念都在哪,完全没有头绪.现在也只 ...

  2. Vue源码学习三 ———— Vue构造函数包装

    Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...

  3. Vue源码学习二 ———— Vue原型对象包装

    Vue原型对象的包装 在Vue官网直接通过 script 标签导入的 Vue包是 umd模块的形式.在使用前都通过 new Vue({}).记录一下 Vue构造函数的包装. 在 src/core/in ...

  4. 最新 Vue 源码学习笔记

    最新 Vue 源码学习笔记 v2.x.x & v3.x.x 框架架构 核心算法 设计模式 编码风格 项目结构 为什么出现 解决了什么问题 有哪些应用场景 v2.x.x & v3.x.x ...

  5. 【Vue源码学习】依赖收集

    前面我们学习了vue的响应式原理,我们知道了vue2底层是通过Object.defineProperty来实现数据响应式的,但是单有这个还不够,我们在data中定义的数据可能没有用于模版渲染,修改这些 ...

  6. Vue 源码学习(1)

    概述 我在闲暇时间学习了一下 Vue 的源码,有一些心得,现在把它们分享给大家. 这个分享只是 Vue源码系列 的第一篇,主要讲述了如下内容: 寻找入口文件 在打包的过程中 Vue 发生了什么变化 在 ...

  7. VUE 源码学习01 源码入口

    VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...

  8. Vue源码学习(一):调试环境搭建

    最近开始学习Vue源码,第一步就是要把调试环境搭好,这个过程遇到小坑着实费了点功夫,在这里记下来 一.调试环境搭建过程 1.安装node.js,具体不展开 2.下载vue项目源码,git或svn等均可 ...

  9. 【Vue源码学习】响应式原理探秘

    最近准备开启Vue的源码学习,并且每一个Vue的重要知识点都会记录下来.我们知道Vue的核心理念是数据驱动视图,所有操作都只需要在数据层做处理,不必关心视图层的操作.这里先来学习Vue的响应式原理,V ...

  10. Vue.js 源码分析(十九) 指令篇 v-html和v-text指令详解

    双大括号会将数据解释为普通文本,而非 HTML 代码.为了输出真正的 HTML,你需要使用 v-html 指令,例如: <!DOCTYPE html> <html lang=&quo ...

随机推荐

  1. pandas -- DataFrame的级联以及合并操作

    博客地址:https://www.cnblogs.com/zylyehuo/ 开发环境 anaconda 集成环境:集成好了数据分析和机器学习中所需要的全部环境 安装目录不可以有中文和特殊符号 jup ...

  2. 低代码平台如何借助Nginx实现网关服务

    摘要:本文由葡萄城技术团队于博客园原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 在典型的系统部署架构中,应用服务器是一种软件或硬件系统, ...

  3. Django框架项目之课程主页——课程页页面、课程表分析、课程表数据、课程页面、课程接口、前台、后台

    文章目录 1-课程页页面 课程组件 2 课程主页之课程表分析 课程表分析 免费课案例 创建models:course/models.py 注册models:course/adminx.py 数据库迁移 ...

  4. CefSharp自定义滚动条样式

    在WinForm/WPF中使用CefSharp混合开发时,通常需要自定义滚动条样式,以保证应用的整体风格统一.本文将给出一个简单的示例介绍如何自定义CefSharp中滚动条的样式. 基本思路 在前端开 ...

  5. 基本操作:vscode快捷键

      1.复制,剪切 补选中具体内容的话,光标放在这一行的任何位置,输入Ctrl+C,就表示已经复制这一行了:直接Ctrl+V可以粘贴: 截切也一样:光标放在这一行的任何位置,输入Ctrl+X,就表示已 ...

  6. js下IE和FF的一些兼容写法总结

    一.脚本差异: 1.事件绑定:addEventListener 与 attachEvent  事件处理函数中this指向不同, IE中指向window 2.获取事件对象 :事件处理函数     win ...

  7. 用阿里云镜像Centos7通过rpm和源码编译方式安装MySQL5版本

    这里只说明安装和注意事项,更具体的配置如端口号.cnf文件配置等就不写了. 阿里云开源镜像站资源目录 (aliyun.com) 我用的是基础版本. 基础版本镜像是默认不联网的,可以用下面的命令ping ...

  8. java——1.变量和数据类型

    变量和数据类型 字符.字节.位之间的关系 1.字符:人类可以阅读的文本内容最小单位 ​ 字符编码:utf-8,gbk 2.字节:1字符=2字节:1字符=4字节 3.位:1字节=8位 位指的是二进制位, ...

  9. 纯css步骤条编写

    .steps { position: relative; margin-bottom: 30px; counter-reset: step; /*创建步骤数字计数器*/ } /*步骤描述*/ .ste ...

  10. 仅需三行代码! C# 快速实现PDF转PPT

    一般在会议.教学或培训活动中,我们都会选择PPT文档来进行内容展示.与PDF文档相比,PPT文档具有较强的可编辑性,可以随时增删元素,并且还可以设置丰富多样的动画效果来吸引观众注意.那么如何通过C#将 ...