2021-03-06-【UI组件库】10分钟搞定自定义vue组件库

10分钟搞定自定义vue组件库:kissing_cat:

前言:sunny:

随着项目的日趋壮大,有时候原有的组件不能满足我们的各种需求,就需要在原有的组件上进行改造。自定义的个性化UI组件越来越多,为了更好地管理它们,同时提高组件的可复用性、扩展性,决定打造一套完整的UI组件库。

技术栈:sunny:

  • vue-cli3
  • vue2.X的基本语法
  • npm的发布

完整项目目录结构:sunny:

wwlocal-ui
├─ .eslintrc.js
├─ .gitignore
├─ .npmignore
├─ babel.config.js
├─ docs   // vuepress开发目录
│  ├─ .vuepress
│  │  ├─ components   // 在markdown中可以使用的vue组件
│  │  │  ├─ ww-search-bar.vue
│  │  ├─ config.js   // vurepess配置修改入口,包括左边sidebar,右上方nav导航菜单等
│  ├─ README.md
│  └─ views
│     ├─ basic-components
│     │  ├─ searchBar.md
│     └─ business-components
│        ├─ xxx.md
├─ package-lock.json
├─ package.json   // 与npm发布相关,记录版本号,包入口文件地址
├─ packages   // 组件库源码目录
│  ├─ search
│  │  ├─ index.js
│  │  └─ src
│  │     └─ search.vue
│  ├─ index.js   // 组件库源码组件入口文件,执行npm run build的目标文件
├─ public   //公共资源入口,如favicon
│  ├─ favicon.ico
│  └─ index.html
├─ static   //静态资源入口,如icon图标
│  ├─ image 
├─ README.md
├─ demo
│     └─ page
│  │     └─ testSearchBar.vue
│  ├─ App.vue
│  ├─ main.js
├─ vue.config.js

创建项目:sunny:

项目名起自己觉得有意义的名字就行了

$ vue create demo-ui

注意:由于我们是开发一个第三方依赖库,我们选择 Manually select features

选择那些特性需要安装在项目中

 (*) Babel
 ( ) TypeScript
 ( ) Progressive Web App (PWA) Support
 ( ) Router
 ( ) Vuex
 (*) CSS Pre-processors
 (*) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing

系统默认的包含了基本的 Babel + ESLint 设置的 preset,我们只需要选择CSS配置。移动键盘上下键选择需要的特性,按下键盘空格键即可选中

安装哪一种 CSS 预处理语言

  Sass/SCSS (with dart-sass)
  Sass/SCSS (with node-sass)
  Less
  Stylus

由于政务微信中的样式采用Sass,所以我们选择第一项即可 为什么不选择第二项呢? 因为dart-sassnode-sass更好下载

选择代码风格

  ESLint with error prevention only
  ESLint + Airbnb config
  ESLint + Standard config
  ESLint + Prettier

一般选 ESLint + Prettier的组合

那种方式进行代码格式检测

 (*) Lint on save
 ( ) Lint and fix on commit

选择Ctrl+S保存时检测代码格式即可

配置文件生成方式

  In dedicated config files
  In package.json

看个人喜好,我选第一种

是否保存预配置

Save this as a preset for future projects? (y/N)

看项目需要,我这里选择 N。回车后,系统会自动帮我们把选择的配置集成到模板中,然后生成一个完整的项目。

调整目录:sunny:

将src目录改为demo,用于测试我们自己开发的UI组件(在引入vuepress之后这个文件夹也不再需要了)。在根目录中创建一个packages目录用来存放我们要开发的UI组件;

新增packages目录,该目录未加入webpack编译;

注:cli3 提供一个可选的 vue.config.js 配置文件。如果这个文件存在则他会被自动加载,所有的对项目和webpack的配置,都在这个文件中。

注: vue的package文件夹采用了monorepo:monorepo是一种将多个package放在一个repo中的代码管理模式,摒弃了传统的多个package多个repo的模式。关于monorepo可以在 Vue3.0 中的 monorepo 管理模式这篇文章中了解

webpack配置修改:sunny:

packages 是我们新增的一个目录,默认是不被 webpack 处理的,所以需要添加配置对该目录的支持。

chainWebpack 是一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。在根目录创建vue.config.js文件,作如下配置:

// 修改 src 为 demo
const path = require("path");
module.exports = {
  pages: {
    index: {
      entry: "demo/main.js",
      template: "public/index.html",
      filename: "index.html"
    }
  },
  // 扩展 webpack 配置,使 packages 加入编译
  chainWebpack: config => {
    config.module
      .rule("js")
      .include.add(path.resolve(__dirname, "packages"))
      .end()
      .use("babel")
      .loader("babel-loader")
      .tap(options => {
        return options;
      });
  }
};

组件编写:sunny:

SearchBar 组件

  1. packages 目录下,所有的单个组件都以文件夹的形式存储,所有这里创建一个目录 search
  2. search 目录下创建 src 目录存储组件源码
  3. search 目录下创建 index.js 文件对外提供对组件的引用。
import SearchBar from './src/index.vue';
import { COMPONENT_PREFIX } from '../constants'

// 为组件提供 install 安装方法,供按需引入
SearchBar.install = function(Vue) {
  Vue.component(COMPONENT_PREFIX + SearchBar.name, SearchBar);
};
export default SearchBar;
  1. /packages/search/src/index.vue核心组件代码。

导出所有组件:sunny:

  • 整合所有的组件,对外导出,即一个完整的组件库 修改 /packages/index.js 文件,对整个组件库进行导出:
import Package from '../package.json';
import SearchBar from './search';
import { COMPONENT_PREFIX } from './constants'

// 存储组件列表
const components = { SearchBar };
const component_version = Package.version

// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function(Vue) {
  // 遍历注册全局组件
  Object.keys(components).forEach(function(key) {
    const item = components[key]
    if (item.install) {
      Vue.use(item);
    } else if (item.name) {
      // 统一加 组件前缀
      const name = COMPONENT_PREFIX + item.name
      console.log(name)
      Vue.component(name, item);
    }
  });
};
// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue);
}
export default {
  // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
  version: component_version,
  install,
  ...components
};

组件库打包

  • package.json 中的script下新增一条编译为库的命令,然后就可以使用npm run lib命令进行打包啦
"scripts": {
    "lib": "vue-cli-service build --target lib --name zyx-ui --dest lib packages/index.js"
  },

注:

  1. --target: 构建目标,默认为应用模式。这里修改为 lib 启用库模式。
  2. dest : 输出目录,默认 dist。这里我们改成 lib
  3. [entry]: 最后一个参数为入口文件,默认为 src/App.vue。这里我们指定编译 packages/ 组件库目录
  • 执行编译库命令
npm run lib

npm发布包

  • 首先创建一个npm账户 $ npm adduser 注册一个内部用户,具体操作同npm,可以自行百度。

  • 配置 package.json 文件中发布到 npm 的字段

  1. name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
  2. version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
  3. description: 项目描述。
  4. main: 入口文件,该字段需指向我们最终编译后的包文件。
  5. keyword:关键字,以空格分离希望用户最终搜索的词。
  6. author:作者
  7. private:是否私有,需要修改为 false 才能发布到 npm
  8. license: 开源协议
  9. browserslist: 指定了项目的目标浏览器的范围
  10. repository: 指定代码所在的位置
  • 执行发布指令
npm publish
  • 另外,可在24小时内对已发布的包进行撤回操作 npm unpublish 你的包名

如果失败可加上 --force参数