深入了解vue-router原理并实现一个小demo
目录
- 插件编写的基本方法
- 需求分析
- 我们先看看vue-router的使用步骤
- 由此我们看看vue-router内部做了什么?
- 实现思路
- 首先我们看看如何将$router挂载到组件上?
- ?如何实现那两个路由组件
- 先来看看router-link
- 完整demo代码
- 总结
插件编写的基本方法 推荐大家先看看官方给出的插件使用和开发方法
https://vuejs.bootcss.com/guide/plugins.html?
需求分析
我们先看看vue-router的使用步骤
1.use
Vue.use(VueRouter)
注意??:
Vue.use()
主要是调用插件内部的install方法,并将Vue实例作为参数传入?2.new 一个router实例
const router = new VueRouter({// 实例化router传入的参数mode: 'history',base: process.env.BASE_URL,routes})
3.new Vue() ,把实例放在vue的配置项里面
new Vue({router, // 注意router的实例也往里传render: h => h(App)}).$mount('#app')
4.使用路由组件
、
或者在组件中使用this.$router
由此我们看看vue-router内部做了什么?
将$router挂载到全局上实现并声明了两个组件:
、
?实现思路
首先我们看看如何将$router挂载到组件上?
let Vue; // 保存vue的构造函数,避免打包将其打进去VueRouter.install = function (_Vue) {Vue = _Vue; console.log("options", Vue.$options); Vue.mixin({beforeCreate() {console.log("inner", this); console.log(" this.$options.router", this.$options.router); if (this.$options.router) {Vue.prototype.$router = this.$options.router; }},}); console.log("end"); };
文章图片
可以看到:
1、第一次执行的时候,即在Vue.use(Router)时,还没有实例化vue(因为
Vue.use()
发生在 new Vue()
之前),所以Vue.$option本身是拿不到的(ps: option就是new Vue()
时传入的参数,router也往里面传),此时既然拿不到router的实例,所以不能直接在install方法里面挂载;?【深入了解vue-router原理并实现一个小demo】?2、我们可以在use的时候做一个全局混入,在合适的时间点,获取到Vue根实例配置项中的router实例, 执行挂载。紧接着在new Vue()根实例创建的时候,因为注入了router实例,所以再执行全局混入(mixin)中的生命周期时,这个时候根实例的配置项
this.$options
已经包含了router实例,可以此时把router挂载到Vue的原型上。之后所有Vue实例扩展来的VueCompont都可以通过this.$router
访问到这个属性?如何实现那两个路由组件
先看看路由组件如何使用
Home |About
由上面可以看出,点击
router-link
,就相当于点了a标签,然后a标签的href属性控制页面路由发生了变化;监听路由变化,然后仔router-view里面输出不同的模板;?先来看看router-link
class VueRouter {constructor(options) {// 接受传入的参数this.$options = options; const initial = "/"; // 将current变成响应式数据,//这样在hashchange的回掉中修改curent时,//用到current的router-view的render函数就会重新渲染Vue.util.defineReactive(this, "current", initial); // 监听路由变化window.addEventListener("hashchange", () => {// 获取当前url中的hashthis.current = window.location.hash.slice(1); }); }}VueRouter.install = function (_Vue) {Vue = _Vue; Vue.component("router-view", {render(h) {// 获取当前路由所对应的组件,然后把它渲染出来const { current, $options } = this.$router; // 这里要注意 我们传进来的routes是一个路由表,如下图一// 所以这里我们是找出匹配到当前current路由的项,然后直接渲染组件const route = $options.routes.find((item) => {return item.path === current; }); let component = route ? route.component : null; return h(component); },}); }
?再来看看router-view
class VueRouter {constructor(options) {// 接受传入的参数this.$options = options; const initial = "/"; // 将current变成响应式数据,//这样在hashchange的回掉中修改curent时,//用到current的router-view的render函数就会重新渲染Vue.util.defineReactive(this, "current", initial); // 监听路由变化window.addEventListener("hashchange", () => {// 获取当前url中的hashthis.current = window.location.hash.slice(1); }); }}VueRouter.install = function (_Vue) {Vue = _Vue; Vue.component("router-view", {render(h) {// 获取当前路由所对应的组件,然后把它渲染出来const { current, $options } = this.$router; // 这里要注意 我们传进来的routes是一个路由表,如下图一// 所以这里我们是找出匹配到当前current路由的项,然后直接渲染组件const route = $options.routes.find((item) => {return item.path === current; }); let component = route ? route.component : null; return h(component); },}); }
图一
文章图片
完整demo代码
// 我们要实现什么// 1、插件// 2、两个组件// 保存vue的构造函数,避免打包将其打进去let Vue; class VueRouter {constructor(options) {this.$options = options; const initial = "/"; Vue.util.defineReactive(this, "current", initial); this.current = "/"; window.addEventListener("hashchange", () => {// 获取当前url中的hashthis.current = window.location.hash.slice(1); }); }}// 参数1在Vue.use()调用时传进来,VueRouter.install = function (_Vue) {Vue = _Vue; console.log("options", this); // 全局混入// 目的:延迟下面的逻辑 到 router创建完毕并且附加到选项上时才执行Vue.mixin({// 在每个组件创建实例时都会执行beforeCreate() {// this.$options.router ;即new Vue时放进去的router实例if (this.$options.router) {Vue.prototype.$router = this.$options.router; }},}); // 注册并且实现两个组件Vue.component("router-link", {props: {to: {required: true,},},render(h) {return h("a",{attrs: { href: "#" + this.to },},this.$slots.default); },}); Vue.component("router-view", {render(h) {// 获取当前路由所对应的组件,然后把它渲染出来const { current, $options } = this.$router; const route = $options.routes.find((item) => {return item.path === current; }); let component = route ? route.component : null; return h(component); },}); }; export default VueRouter;
总结 本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
推荐阅读
- 20个你应该了解的Flutter库
- HTTP都到3.0了,你还不了解1和2吗()
- 深入浅出特征工程|深入浅出特征工程 -- 基于 OpenMLDB 的实践指南(下)
- 大数据时代下,App数据隐私安全你真的了解么()
- 遵循Promises/A+规范,深入分析Promise实现细节 | 通过872测试样例
- 深入浅出归并排序(一)
- 为IP地址签发SSL证书
- 深入了解python装饰器
- 快速了解常用的对称加密算法,再也不用担心面试官的刨根问底
- 深度学习|详解深度学习之 Embedding