1

插件通常用来为 Vue 添加全局功能,一般有下面几种:

  1. 添加全局方法或者属性。
  2. 添加全局资源:指令/过滤器/过渡等。
  3. 通过全局混入来添加一些组件选项。
  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。

更加详细说明查看官网文档 https://cn.vuejs.org/v2/guide...

开发插件

1.简单的插件
创建一个countdown.vue

<template>
  <div>封装一个最简单的插件</div>
</template>
<script>
  export default {
    name: 'count-down'
  }

</script>

创建一个index.js

import countDown from './countdown';

//暴露一个 `install` 方法。这个方法的第一个参数是 `Vue` 构造器,第二个参数是一个可选的选项对象
countDown.install = function (Vue) {
  Vue.component(countDown.name, countDown);
};

export default countDown;

目录结构为:
snipaste_20200412_111210.png

在main.js中引入,页面中<count-down></count-down>就可以使用

import countDown from './components/global/index';
//通过全局方法 `Vue.use()` 使用插件
Vue.use(countDown);

2.添加全局方法或属性

countDown.install = function (Vue) {
  Vue.prototype.$msg = '全局的属性';
  Vue.prototype.$myMethod = function () {
    console.log('全局定义的方法');
  }
  Vue.component(countDown.name, countDown);
};

3.添加全局资源


countDown.install = function (Vue) {
  //全局自定义指令
  Vue.directive('focus', {
    //当节点插入的时候
    inserted: function (el) {
      el.focus();
    }
  })
  Vue.component(countDown.name, countDown);
};

4.注入组件选项

countDown.install = function (Vue) {
  //全局混入
  Vue.mixin({
    created() {
      console.log('i am jello')
    },
  })
  Vue.component(countDown.name, countDown);
};

开发插件进阶

创建一个VsButton.vue

<template>
  <button class="vs-button" :class="type" @click="fn">
    <slot></slot>
  </button>
</template>

<script>
  export default {
    name: 'VsButton',
    props: {
      type: {
        type: String,
        default: 'warning'
      }
    },
    methods: {
      fn() {
        this.$emit('click');
      }
    },
  }

</script>

<style lang='less' scoped>
  .vs-button {
    width: 100px;
    height: 40px;
    background: #ccc;
    border-radius: 4px;
  }

  .warning {
    background: yellow
  }

  .danger {
    background: red
  }

  .success {
    background: green
  }

</style>

创建VsMsg.vue

<template>
  <transition name="fade">
    <div class='vs-msg' v-show='visible'>
      <img src='../../../assets/msg.png' class='pic' />
      <span class='msg-text' @click='close'>
        <slot></slot>
      </span>
    </div>
  </transition>
</template>

<script>
  export default {
    name: 'VsMsg',
    props: {
      visible: {
        type: Boolean,
        default: false
      }
    },
    methods: {
      close() {
        this.$emit('update:visible', false);
      }
    },
  }

</script>

<style lang='less' scoped>
  .vs-msg {
    width: 330px;
    min-height: 280px;
    display: flex;
    flex-direction: column;
    padding: 30px;
    background: #eee;

    .pic {
      width: 100%;
      height: 200px;
    }

    .msg-text {
      height: 80px;
      line-height: 80px;
      background: rgba(255, 255, 255, 1);
      border-radius: 0px 0px 10px 10px;
      font-size: 16px;
      color: rgba(255, 162, 26, 1);
    }
  }

  .fade-enter-active,
  .fade-leave-active {
    transition: opacity .3s ease;
  }

  .fade-enter,
  .fade-leave-to {
    opacity: 0;
  }

</style>

创建一个index.js

import VsMsg from '../plugins/msg/VsMsg';
import VsButton from '../plugins/button/VsButton';

let plugin = {};

plugin.install = function (Vue) {
  Vue.component(VsMsg.name, VsMsg);
  Vue.component(VsButton.name, VsButton);
}

export default plugin;

每次使用都需要import和Vue.component(),可采用webpack的require.context(),实现自动导入和注册组件。

1)require.context函数接受三个参数:

  • directory {String} -读取文件的路径
  • useSubdirectories {Boolean} -是否遍历文件的子目录
  • regExp {RegExp} -匹配文件的正则

2)require.context函数执行后返回的是一个函数,并且这个函数有3个属性

  • resolve {Function} -接受一个参数request,request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径
  • keys {Function} -返回匹配成功模块的名字组成的数组
  • id {String} -执行环境的id,返回的是一个字符串,主要用在module.hot.accept
const requireComponent = require.context('./', true, /\.vue$/); //获取一个特定的上下文,主要用来实现自动化导入模块

const install = (Vue) => { 

  if (install.installed) return;
  install.installed;
  requireComponent.keys().forEach(fileName => {
    //第i个组件
    const config = requireComponent(fileName);
    //组件名
    const componentName = config.default.name;

    Vue.component(componentName, config.default || config);
  })

}

//检测环境
if (typeof window !== undefined && window.Vue) {
  install(Vue);
}

export default install;

在main.js中引入

import index from "./components/plugins/index.js";
Vue.use(index);

页面中使用插件

<template>
    <VsButton type='warning' @click="open">默认按钮</VsButton>
    <VsMsg :visible.sync="visible">我是一个消息</VsMsg>
</template>

<script>
  export default {
    data() {
      return {
        visible: false
    },
    methods: {
      open() {
        this.visible = true;
      }
    }
  }
</script>

实现效果如下:
snipaste_20200412_115451.png

上传npm

1.vue-cli 3.x 提供了一个构建库文件打包命令
主要需要四个参数:

  • target: 默认为构建应用,改为 lib 即可启用构建库模式
  • name: 输出文件名
  • dest: 输出目录,默认为 dist,这里我们改为 lib
  • entry: 入口文件路径,默认为 src/App.vue

在 package.json 里的 scripts 添加一个 lib 命令

  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lib": "vue-cli-service build --target lib --name vue-plugins-msg-jello --dest lib src/components/plugins/index.js"
  },

然后执行 npm run lib 命令,编译组件
snipaste_20200413_113653.jpg

2.发布前需要在 package.json 添加组件信息:

  • name: 包名,该名不能和已有的名称冲突
  • version: 版本号,不能和历史版本号相同
  • description: 简介
  • main: 入口文件,应指向编译后的包文件
  • keyword:关键字,以空格分割
  • author:作者
  • private:是否私有,需要修改为 false 才能发布到 npm
  • license:开源协议
  "name": "vue-plugins-msg-jello",
  "version": "0.1.0",
  "private": false,
  "license": "MIT",
  "main": "lib/vue-plugins-msg-jello.umd.min.js",

然后创建 .npmignore 文件,设置忽略文件,该文件的语法和 .gitignore 的语法一样,设置发布到 npm 时忽略哪些目录或文件

.DS_Store
node_modules/
examples/
packages/
public/
vue.config.js
babel.config.js
*.map
*.html

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

3.发布到npm
若以前改过 npm 的镜像地址,比如使用了淘宝镜像,就先改回来
npm config set registry http://registry.npmjs.org

没有 npm 账户,可以通过 npm adduser 命令创建一个账户,或者到 npm 官网注册,具体流程可以参考官方文档

使用 npm login 命令登录,发布时遇到
微信图片_20200413114234.png
去邮箱认证后,再继续npm publish
snipaste_20200413_114851.jpg

发布npm后插件使用

1)安装

 npm i vue-plugins-msg-jello --save

2)main.js引入注册插件

import msg from 'vue-plugins-msg-jello'
import '../node_modules/vue-plugins-msg-jello/lib/vue-plugins-msg-jello.css'
Vue.use(msg)

3)页面使用

<template>
  <div class="about"> 
    <VsButton type="danger">危险按钮</VsButton>
    <VsButton type="warning">警告按钮</VsButton> 
  </div>
</template>

Jello
181 声望20 粉丝

看得越多,懂的越少,还年轻,多学习