插件编写的基本方法

推荐大家先看看官方给出的插件使用和开发方法

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.使用路由组件<router-view/><router-link></router-link>或者在组件中使用this.$router

由此我们看看vue-router内部做了什么?

将$router挂载到全局上实现并声明了两个组件:<router-view/><router-link></router-link>

实现思路

首先我们看看如何将$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方法里面挂载;

​2、我们可以在use的时候做一个全局混入,在合适的时间点,获取到Vue根实例配置项中的router实例, 执行挂载。紧接着在new Vue()根实例创建的时候,因为注入了router实例,所以再执行全局混入(mixin)中的生命周期时,这个时候根实例的配置项this.$options已经包含了router实例,可以此时把router挂载到Vue的原型上。之后所有Vue实例扩展来的VueCompont都可以通过this.$router访问到这个属性

​如何实现那两个路由组件

先看看路由组件如何使用

<div id="app">
  <div id="nav">
    <!-- a标签控制跳转 -->
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
  </div>
  <!-- 路由出口 -->
  <router-view />
</div>

由上面可以看出,点击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中的hash
      this.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中的hash
      this.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中的hash
      this.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;

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注Devmax的更多内容!     

深入了解vue-router原理并实现一个小demo的更多相关文章

  1. PHP实现文件安全下载

    例如你希望客户要填完一份表格,才可以下载某一文件,你第一个想法一定是用"Redirect"的方法,先检查表格是否已经填写完毕和完整,然后就将网址指到该文件,这样客户才能下载,但如果你想做一个关于"网上购物"的电子商务网站,考虑安全问题,你不想用户直接复制网址下载该文件,笔者建议你使用PHP直接读取该实际文件然后下载的方法去做。feof){echofread;}fclose;}这样就可以用PHP直接输出文件了。

  2. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  3. 实现“上一页”和“下一页按钮

    offset=$prevoffset\">上一页\n";}//计算页面数$pages=intval;//$pagesnowcontainsintofpagesneededunlessthereisaremainderfromdivisionif{//hasremaindersoaddonepage$pages;}for{//显示页数$newoffset=$limit*;print"

  4. 五分钟理解keep alive用法及原理

    这篇文章主要为大家介绍了keep alive用法及原理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  5. vue-router如何实时动态替换路由参数(地址栏参数)

    这篇文章主要介绍了vue-router如何实时动态替换路由参数(地址栏参数),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  6. 解决vue路由组件vue-router实例被复用问题

    这篇文章介绍了解决vue路由组件vue-router实例被复用的问题,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. 利用PHP实现与ASP Banner组件相似的类

    ********************************************************//*广告条管理程序publicmethodGetAdvertisementparametersTarget=Width=Height=Border=Redirect=*/classAdRotator{var$Target="_blank";var$Width="460";var$Height="60";var$Border=0;var$Redirect="";var$BannerData=ar

  8. PHP架构及原理知识点详解

    这篇文章主要介绍了PHP架构及原理知识点以及相关实例讲解,需要的朋友们参考下。

  9. DialogFragment运行原理及使用方法详解

    这篇文章主要介绍了DialogFragment运行原理及使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  10. 用Php实现链结人气统计

    php//功能:传入参数id,在计数文件查找相应的url,增加计数,并返回实际的链接$countfile="count.txt";$lines=file;//将计数文件内容读到数组$lines中for{list=explode;//分解字符串为$id,$url,$countif//查找指定id{$count=1;//增加计数$lines[$i]=$sid."|".$url."|"."$count"."\n";//重新生成计数字符串break;}}//写入计数信息$fp=fopen;forfputs;fcl

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部