前言

  • vue.js作为前端三大框架之一,它的快速开发特点深受开发者的喜爱。通常,我们使用vue.js会集成Router、Axios、Vuex、Element-UI等插件,那么你知道它们是如何无缝对接vue.js的吗?接下来,我们参考Router插件无缝对接vue.js的原理来手动开发一个插件,并以npm的方式导入项目中。你准备好了吗?(ps:接下来的内容,你需要有ES6语法基础、Vue.js插件,混入,组件,指令相关知识点才能看懂)

一、vue-router集成vue.js的原理

  • 我们知道,在使用vue-cli2.0脚手架搭建vue.js项目时,它支持Router的选项,如下所示:
    在这里插入图片描述
    当我们输入Y时,Router插件就在项目中生效了。如果我们要添加路由,直接修改router/index.js文件即可,如下所示(为HelloWorld页面再添加一个路由):
    在这里插入图片描述
    毋庸置疑,在使用vue-cli2.0脚手架搭建项目时,针对于Router这个插件内部肯定做了很多事,今天咱们不深究到底做了哪些事,咱们来探究下main.js的内容:
    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from 'vue'
    import App from './App'
    import router from './router'
    
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      // 这里用了ES6的简便语法,
      // 实际为:  router: router, 当key和value的名称一致时,可以省略冒号
      router,  	  
      components: { App },
      template: '<App/>'
    })
    
    有一个可疑点,就是在传入new Vue() 构造方法的参数中,为什么添加了router,难道这样就能无缝集成vue.js了吗?我们不得而知,但是从官网插件部分内容来看[点击查看],还需要使用类似Vue.use(router)的代码来将路由集成至vue.js中。那么,这段代码是在哪里被执行的呢?我们从main.js中开始看,可以看到这么一段代码:
    import router from './router'
    
    于是我们定位至router文件夹中去,发现内部存在一个index.js文件,其内部就是我们定义路由的内容:
    在这里插入图片描述
    其中,我们很容易发现,内部执行了这么一段代码:
    Vue.use(Router)
    
    突然发现,好像是符合官网的规则。那为什么还需要在main.js中的new Vue()有参构造方法中传入router呢?这里又涉及到了Vue.js的全局混入的知识点[点击查看]
    在这里插入图片描述
    根据全局混入知识点可知,它有缺点:每当创建一个Vue实例时,都会进行混入。白话来讲就是:每创建一个Vue实例,都会调用上图的created钩子函数。从上述图中的代码来看,console.log(myOption)这行代码的执行是有条件的,只有当前vue实例的$options对象中的myOption属性为true才能正常执行。那么我们是不是可以大致猜测下:router插件集成vue.js的原因就是基于插件 + 混入来实现的? 可以自己做个实验:把main.js中Vue的构造方法中的router删除后,看项目还是否能够正常路由至HelloWorld页面

二、如何自定义插件

  • 可以细看官网demo。说实话,vue.js官网真的很nice,基本上所有vue.js的功能都可以在官网中找到demo(读到这里的你,是否发觉官网的重要性了呢?)。现在,咱们直接利用官网的demo,来实现一个插件,包含如下功能:

    1.拥有一个SayHi组件,其中拥有一个叫content的props,默认值为avengerEug。
    实现的功能 :在浏览器中渲染出: Hi {{ content }} (其中content为默认值或传入的值)
    2.拥有一个avenger-eug的指令,传入一个字体的style颜色样式
    实现的功能:当传入red时,标签中的字体颜色变成红色
    3.拥有一个全局弹框方法
    实现的功能:当我们执行this.$myMessage(‘Hello’)时,会在页面弹出一个alert框,且内容为Hello

  • 实现步骤

    • 第一:创建如下图所示的目录结构:
      在这里插入图片描述

    • 第二:在src/myPlugin/index.js文件中填充如下内容:

      export default {
        install: (Vue) => {
          Vue.mixin({
            created: function () {
              // 当在vue的构造方法中,存在avengerEug这个key时,就会
              // 创建全局组件、指令和方法
              if (this.$options.avengerEug) {
                
                Vue.prototype.$myMessage = function (params) {
                  window.alert(params)
                }
      
                Vue.component('SayHi', {
                  template: '<h1> Hi {{ content }} </h1>',
                  props: {
                    content: {
                      type: String,
                      default: () => { return 'avengerEug' }
                    }
                  },
                  created() {
                    console.log('调用了SayHi组件的created钩子函数')
                  }
                })
      
                Vue.directive('avenger-eug', {
                  bind(el, binding, vnode, oldVnode) {
                    if (binding.value) {
                      el.style.color = binding.value
                    }
                  }
                })
      
              }
            }
          })
        }
      }
      
    • 第三:在main.js中添加如下代码:
      在这里插入图片描述

    • 第四:校验:
      在这里插入图片描述
      由上可知,我们使用插件 + 混入的方式将自己写的插件给集成到了当前项目中了。这里提一句:为什么我们写的组件、指令、方法都能在其他组件中不需要注册而直接使用呢?还记得官网中对插件章节的描述么?它要求第一个参数为Vue对象,而且必须要在new Vue代码之前执行Vue.use相关的代码。那只有一个说法能够说明,那就是在执行new Vue构造方式时,内部对所有的插件进行了遍历,并把自己作为参数,调用每个插件的install方法,而此时的this就是全局Vue对象。 可能有人会问:我想把我的插件发布至npm中,后续其他项目直接使用npm install my-plugin时就能把上述的三个功能给加到项目中去,那该怎么办?咱们继续往下看。

三、如何跨项目依赖自己的插件

  • 在第二章中,我们实现了自定义的插件,并且集成到当前项目中去了。那么要如何跨项目依赖自己编写的插件呢?这里就需要把自己的插件打成包发布至npm中去了。不急,咱们来搞定它!

  • 步骤如下:

    1.使用vuecli2.0脚手架搭建简单版本vue.js项目(防止插件依赖过多的类库)

    # 注意,项目名必须唯一,不然在发布时会报403错误,npm认为你要更新别人的插件
    # 但是发现不是同一个人,所以会报无权限
    vue init webpack-simple my-plugin-avenger
    

    在这里插入图片描述
    在这里插入图片描述
    ps: 上述的项目名为my-plugin-avenger,先记住它,后续我们在npm install 和 import都需要用到它。

    2.编写自定义插件,为了方便,我直接copy第二章创建插件的代码,最终内容如下所示:
    在这里插入图片描述

    3.创建src/index.js文件(为了将插件打包),如下所示:
    在这里插入图片描述

    4.修改webpack.config.js文件
    在这里插入图片描述

    // 对应的修改内容如下:
    module.exports = {
      entry: './src/index.js',
      output: {
        // 模块名, 其他类库使用require的方式引用的原因就是配置了这个
        library: 'my-plugin-avenger',
        // libraryTarget会生成不同umd的代码,可以只是commonjs标准的,也可以是指amd标准的,也可以只是通过script标签引入的
        libraryTarget: 'umd',
        umdNamedDefine: true,  // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
        // 后面内容省略 
      },
      // 后面内容省略
    }
    

    5.修改package.json文件,指定插件入口
    // 修改如下配置。因为需要发布, 因此需要将这个字段改为 false
    "private": false,
    // 新增如下配置。当在第三方使用类库, 使用 import MyPluginAvenger from 'my-plugin-avenger’时, 会根据插件的package.json的main入口找文件
    "main": "dist/build.js",

    6.执行npm install引入依赖

    7.执行npm run build打包
    在这里插入图片描述

    8.自己在npm中注册账号(若已有账号,此步骤忽略)

    9.设置npm config set registry http://registry.npmjs.org/命令配置npm源

    10.执行npm adduser命令绑定账号,输入如下信息:
    Username: your name
    Password: your password
    Email: yourmail

    11.更新项目中的README.md文件内容,描述该插件有何用,如何使用(当在npm官网查找插件时,可以看到)。本人图方便,未更改。

    12.执行npm publish命令发布npm包
    在这里插入图片描述

    13.npm官网查看发布的插件
    在这里插入图片描述

    14.跨项目依赖,在项目中执行:npm i my-plugin-avenger

    15.在项目的main.js中加入如下代码:

    import MyPluginAvenger from 'my-plugin-avenger'
    Vue.use(MyPluginAvenger)
    
    // 并在vue构造器中添加avengerEug: true
    
    new Vue({
      el: '#app',
      router,
      components: { App },
      template: '<App/>',
      avengerEug: true
    })
    

    16.在任意页面使用第二章所说的组件、指令和全局函数,你会发现,成功了!

四、总结

  • 在npm发布的过程中,会出现一些其他错误,如下:

    错误原因
    no_perms Private mode enable, only admin can publish this module默认镜像非官方的, 需要重新设置.命令: npm config set registry http://registry.npmjs.org
    npm publish failed put 500 unexpected status code 401没有登录,需要登录: npm login 即可
    npm ERR! you do not have permission to publish “your module name”. Are you logged in as the correct user?包名被占用, 需要重新命名. 命名之前最好先去npm官网查看包名是否被占用
    You cannot publish over the previously published versions每次发布时需要更新版本, 修改package.json文件的version字段即可.
    npm publish时经常报403可以确认下注册的账号是否在邮箱中验证完毕,或确认发布的项目名是否唯一
  • I am a slow walker, but I never walk backwards.

Logo

前往低代码交流专区

更多推荐