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-sass
比node-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 组件
- 在
packages
目录下,所有的单个组件都以文件夹的形式存储,所有这里创建一个目录search
- 在
search
目录下创建src
目录存储组件源码 - 在
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;
/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"
},
注:
--target
: 构建目标,默认为应用模式。这里修改为 lib 启用库模式。dest
: 输出目录,默认 dist。这里我们改成 lib[entry]
: 最后一个参数为入口文件,默认为 src/App.vue。这里我们指定编译 packages/ 组件库目录
- 执行编译库命令
npm run lib
npm发布包
-
首先创建一个npm账户
$ npm adduser
注册一个内部用户,具体操作同npm,可以自行百度。 -
配置
package.json
文件中发布到npm
的字段
- name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
- version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
- description: 项目描述。
- main: 入口文件,该字段需指向我们最终编译后的包文件。
- keyword:关键字,以空格分离希望用户最终搜索的词。
- author:作者
- private:是否私有,需要修改为 false 才能发布到 npm
- license: 开源协议
- browserslist: 指定了项目的目标浏览器的范围
- repository: 指定代码所在的位置
- 执行发布指令
npm publish
- 另外,可在24小时内对已发布的包进行撤回操作
npm unpublish 你的包名
如果失败可加上 --force
参数