一篇文章,教你学会Vue CLI 插件开发


Posted in Javascript onApril 17, 2019

前言

如果你正在使用Vue框架,那么你肯定知道Vue CLI是什么。Vue-cli 3,它是Vue.js 开发的标准工具(脚手架),提供项目支架和原型设计。

除了日常构建打包项目,Vue CLI3 的一个重要部分是cli-plugins,插件开发。

本文将教你如何科学的创建一个Vue-CLI 插件,以及项目独立npm包。

1. 什么是CLI plugin

它可以修改内部webpack配置并将命令注入到vue-cli-service。一个很好的例子是@vue/cli-plugin-typescript:当你调用它时,它会tsconfig.json为你的项目添加一个并更改App.vue类型,整个过程不需要手动执行。
插件非常有用,但有很多不同的情况: Electron构建器,添加UI库,如iview或ElementUI ....如果你想为某个特定的库提供一个插件但却不存在呢?这时候,构建一个属于自己项目的插件就是个不错的选择。

一篇文章,教你学会Vue CLI 插件开发

在本文中,我们将构建一个vue-cli-plugin-rx。它允许我们向项目添加vue-rx库,并在我们的Vue应用程序中获得RxJS支持

2. Vue-cli插件目录结构

CLI 插件是一个可以为 @vue/cli项目添加额外特性的 npm 包。它应该始终包含:

  1. 一个Service插件作为其主要导出
  2. 可选的包含一个 Generator 和一个 Prompt 文件。

.
├── README.md
├── generator.js  # generator (可选)
├── prompts.js    # prompt 文件 (可选)
├── index.js      # service 插件
└── package.json

如果你需要在插件安装的同时,通过命令行来选择是否创建一些示例组件,那么目录可以改为:

 .
├── README.md
├── generator
│   └── index.js  # generator
├── prompts.js    # 命令行提示安装
├── index.js      # service 插件
└── package.json

2.1 GeneratorAPI

一个发布为 npm 包的 CLI 插件可以包含一个 generator.js 或 generator/index.js 文件。插件内的 generator 将会在两种场景下被调用:

在一个项目的初始化创建过程中,如果 CLI 插件作为项目创建 preset 的一部分被安装。
插件在项目创建好之后通过 vue invoke 独立调用时被安装。

GeneratorAPI允许一个 generator 向 package.json 注入额外的依赖或字段,并向项目中添加文件。

2.2 Service 插件

Service 插件接收两个参数的函数:一个PluginAPI实例和一个包含项目本地选项的对象。它可以扩展/修改不同环境的内部webpack配置,并为其注入其他命令vue-cli-service。
但在这里,我们只想在必要时添加一些依赖项和示例组件。所以我们的index.js长这样:

module.exports = (api, opts) => {}

如果你想改变内部webpack配置或其它操作,请在官方Vue CLI文档中阅读本节

2.3 Package.json

keywords 指定了在库中搜索时能够被哪些关键字搜索到,所以一般这个会多写一些项目相关的词在这里,是一个字符串的数组。

{
 "name": "vue-cli-plugin-rx",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "keywords": [
 "vue",
 "vue-cli",
 "rxjs",
 "vue-rx"
 ],
 "author": "",
 "license": "ISC"
}

3. 通过generator添加依赖项

generator可帮助我们添加依赖项并更改项目文件。所以,我们需要的第一步是让我们的插件添加依赖项:rxjs和vue-rx(你也可以添加其它):

// generator/index.js
module.exports = (api, options, rootOptions) => {
 api.extendPackage({
 dependencies: {
 'rxjs': '^6.3.3',
 'vue-rx': '^6.1.0',
 },
 });
}

generator 导出一个接收三个参数的函数:GeneratorAPI实例,生成器选项和 - 如果用户使用某个预设创建项目 - 整个预设将作为第三个参数传递。

api.extendPackage方法将会修改项目的package.json。

在本文的例子中,我们将两个依赖项添加到dependencies。

现在我们需要更改main.js文件。为了使RxJS能在Vue组件中工作,我们需要导入VueRx和调用Vue.use(VueRx)

首先,我们创建一个想要添加的字符串到主文件:

let rxLines = `\nimport VueRx from 'vue-rx';\n\nVue.use(VueRx);`;

 使用api.onCreateCompletehook。在文件写入磁盘时调用它:

api.onCreateComplete(() => {
 const fs = require('fs');
 const mainPath = api.resolve(''./src/main.js');
};

现在我们修改文件内容:

api.onCreateComplete(() => {
 const fs = require('fs');
 const mainPath = api.resolve('./src/main.js');
 // 获取内容
 let contentMain = fs.readFileSync(mainPath, { encoding: 'utf-8' });
 const lines = contentMain.split(/\r?\n/g).reverse();
 // 注入import
 const lastImportIndex = lines.findIndex(line => line.match(/^import/));
 lines[lastImportIndex] += rxLines;
 // 修改应用
 contentMain = lines.reverse().join('\n');
 fs.writeFileSync(mainPath, contentMain, { encoding: 'utf-8' });
 });
};

4. 本地测试cli-plugin

首先我们创建一个简单的Vue-cli项目:

vue create test-app

 cd到项目文件夹并安装我们新创建的插件:

cd test-app
npm install --save-dev file://Users/hiro/练习/测试/vue-plugin

 安装插件后,需要调用它:

vue invoke vue-cli-plugin-rx

 现在,你查看test-app项目的main.js,将会看到:

import Vue from 'vue'
import App from './App.vue'
import VueRx from 'vue-rx';
Vue.use(VueRx);

同时,查看package.json将会发现:

"dependencies": {
  "core-js": "^2.6.5",
  "rxjs": "^6.3.3",
  "vue": "^2.6.10",
  "vue-router": "^3.0.3",
  "vue-rx": "^6.1.0",
  "vuex": "^3.0.1"
 }

5. 通过generator创建示例组件

经过上面的验证,插件已有效。此时,我们可以扩展一下它的功能,创建示例组件,方便其他人理解和使用。

5.1 编写示例组件

我们创建的这个示例组件。它应该是位于项目src/components文件夹中的文件。

于是我们可以在generator目录下,创建/template/src/components:

一篇文章,教你学会Vue CLI 插件开发

这一个简单的RxJS驱动的计数器,带有两个按钮

一篇文章,教你学会Vue CLI 插件开发

源码如下:

<template>
  <section>
    <h1>Click on 'Count' button to count your clicks</h1>
    <button v-stream:click="count$">Count clicks</button>
    <button @click="clearCounter">Clear counter</button>
    <p>{{result$}}</p>
  </section>
</template>

<script>
import {
 filter,
 bufferWhen,
 debounceTime,
 map,
 startWith,
} from 'rxjs/operators';
export default {
 domStreams: ['count$'],
 subscriptions() {
  return {
   result$: this.count$.pipe(
    filter(event => !!event),
    bufferWhen(() => this.count$.pipe(debounceTime(400))),
    map(clicks => clicks.length),
    startWith(0),
   ),
  };
 },
 methods: {
  clearCounter() {
   this.count$.next(null);
  },
 },
};
</script>
<style>
button {
 padding: 10px;
 font-size: 14px;
 margin-right: 10px;
 border-radius: 4px;
 outline: none;
}
</style>

 不需要关心RxJS做了什么(反正我也没看懂),引就vans了。

此时我们需要改动generator/index.js,使它可以识别并写入文件夹。

api.render('./template', {
 ...options,
});

当你调用 api.render('./template')时,generator将会使用 EJS渲染 ./template中的文件 (相对于 generator中的文件路径进行解析)

5.2 命令行提示安装

如果用户是个老手,不想拥有示例组件,该怎么办?在插件安装过程中,我们可以向prompts.js添加提示代码,以供用户在命令行选择:

module.exports = [
 {
  name: `addExample`,
  type: 'confirm',
  message: '是否添加示例组件到项目components目录?',
  default: false,
 },
];

询问用户是否要将示例组件添加到项目components目录下。默认是:false。

这时我们需要修改下generator/index.js:

if (options.addExample) {
  api.render('./template', {
   ...options,
  });
}

一篇文章,教你学会Vue CLI 插件开发

此时我们撤回安装,重新运行

 yarn add --save-dev file://Users/hiro/练习/测试/vue-plugin
vue invoke vue-cli-plugin-rx

 将会看到:

一篇文章,教你学会Vue CLI 插件开发

此时你查看项目components目录,将会发现多了示例组件文件

 一篇文章,教你学会Vue CLI 插件开发

6.如何发布插件

来自官方文档

为了让一个 CLI 插件能够被其它开发者使用,你必须遵循 vue-cli-plugin-<name> 的命名约定将其发布到 npm 上。插件遵循命名约定之后就可以:

被 @vue/cli-service 发现;
被其他开发者搜索到;
通过 vue add <name>或 vue invoke <name> 安装下来。

你只需要在package.json中添加描述description,以及在插件项目根目录下创建logo.png。
接下来就是注册npmjs.com

 2、设置仓库地址为npm官方仓库地址(国内大部分都使用阿里淘宝镜像,如果没改publish会失败)
npm config set registry https://registry.npmjs.org/

3、登陆npm,用户名密码邮箱需要全部匹配
npm whoami
npm login
Username: xxxxx
Password:
Email: (this IS public) xxx@gmail.com
Logged in as xxxxx on https://registry.npmjs.org/.

4、登陆完可以publish了,执行以下命令
cd dist && npm publish && cd ../
或npm publish dist
输出以下信息说明发布成功
+ ngx-xxx@0.0.1
这时登录https://www.npmjs.com/可以看到自己发布的项目

完事。

总结

Vue-CLI插件开发,对于很多项目,当你需要引入一些自己以前编写过的组件或功能,却不想复刻一遍main.js和Package.json,学会了这招,开发贼快。当有人问你如何组织项目的组件库时,啧啧...你说你都是安装自己写的插件。

以上所述是小编给大家介绍的Vue CLI 插件开发详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
读取input:file的路径并显示本地图片的方法
Sep 23 Javascript
Javascript保存网页为图片借助于html2canvas库实现
Sep 05 Javascript
JavaScript更改原始对象valueOf的方法
Mar 19 Javascript
JavaScript中的普通函数与构造函数比较
Apr 07 Javascript
jquery实现带缩略图的全屏图片画廊效果实例
Jun 25 Javascript
使用CDN和AJAX加速WordPress中jQuery的加载
Dec 05 Javascript
AngularJs Understanding the Model Component
Sep 02 Javascript
浅谈jQuery hover(over, out)事件函数
Dec 03 Javascript
微信小程序中做用户登录与登录态维护的实现详解
May 17 Javascript
Layui之table中的radio在切换分页时无法记住选中状态的解决方法
Sep 02 Javascript
详解微信小程序之提高应用速度小技巧
Jan 07 Javascript
vue 导出文件,携带请求头token操作
Sep 10 Javascript
ES6知识点整理之函数数组参数的默认值及其解构应用示例
Apr 17 #Javascript
mpvue性能优化实战技巧(小结)
Apr 17 #Javascript
node.js监听文件变化的实现方法
Apr 17 #Javascript
vue中格式化时间过滤器代码实例
Apr 17 #Javascript
postman自定义函数实现 时间函数的思路详解
Apr 17 #Javascript
vue指令之表单控件绑定v-model v-model与v-bind结合使用
Apr 17 #Javascript
记一次Vue.js混入mixin的使用(分权限管理页面)
Apr 17 #Javascript
You might like
ADODB类使用
2006/11/25 PHP
将CMYK颜色值和RGB颜色相互转换的PHP代码
2014/07/28 PHP
php实现删除空目录的方法
2015/03/16 PHP
php PDO异常处理详解
2016/11/20 PHP
解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
2019/10/03 PHP
常用参考资料(手册)下载或者链接
2006/07/22 Javascript
起点页面传值js,有空研究学习下
2010/01/25 Javascript
JS获取网页属性包括宽、高等等
2014/04/03 Javascript
js取模(求余数)隔行变色
2014/05/15 Javascript
jQuery时间插件jquery.clock.js用法实例(5个示例)
2016/01/14 Javascript
js 获取今天以及过去日期
2017/04/11 Javascript
基于jQuery Easyui实现登陆框界面
2017/07/10 jQuery
浅谈pc端rem字体设置的问题
2017/08/03 Javascript
[js高手之路]设计模式系列课程-发布者,订阅者重构购物车的实例
2017/08/29 Javascript
vue + webpack如何绕过QQ音乐接口对host的验证详解
2018/07/01 Javascript
JavaScript中发出HTTP请求最常用的方法
2018/07/12 Javascript
vue-cli 3.x 修改dist路径的方法
2018/09/19 Javascript
vue表单验证你真的会了吗?vue表单验证(form)validate
2019/04/07 Javascript
Python使用cookielib模块操作cookie的实例教程
2016/07/12 Python
windows下安装Python虚拟环境virtualenvwrapper-win
2019/06/14 Python
Python3+Appium安装使用教程
2019/07/05 Python
Python实现K折交叉验证法的方法步骤
2019/07/11 Python
pygame编写音乐播放器的实现代码示例
2019/11/19 Python
python字符串替换re.sub()实例解析
2020/02/09 Python
基于Python和C++实现删除链表的节点
2020/07/06 Python
Python map及filter函数使用方法解析
2020/08/06 Python
python+selenium自动化实战携带cookies模拟登陆微博
2021/01/19 Python
奥地利领先的在线药房:SHOP APOTHEKE
2019/10/07 全球购物
信息管理员岗位职责
2013/12/01 职场文书
护士思想汇报
2014/01/12 职场文书
保护环境倡议书100字
2014/05/19 职场文书
党在我心中演讲稿
2014/09/02 职场文书
2015届大学生就业推荐表自我评价
2014/09/27 职场文书
2014年网络管理员工作总结
2014/12/01 职场文书
后备干部推荐材料
2014/12/24 职场文书
放假通知范文
2015/04/14 职场文书