基于Vue的npm组件库
前言(*❦ω❦)
思维导图可能有点高糊,有点太大了,项目和导图文件放到github
或giteee
上,这个思维导图也是我文章的架构,思维导图是用FeHelper插件生成的,这个是一款开源chrome插件
,访问地址按照插件项目说明安装即可,然后导入我的思维导图的JSON文件即可,JSON文件会放在项目中。
构建vue npm 组件库需要准备的事(会的同学可跳过)( ゚▽゚)/
这里主要讲一下搭建一个vue组件库需要事先准备的条件,其实也是一个合格的初级前端开发人员的必备条件。
-
编辑器工具: VsCode下载地址
首先是使用工具,个人推荐VsCode
,因为感觉前端用这款软件太合适不过了,各种插件用得好完全可以起飞。 -
git环境:
git
安装可以网上查查资料,安装好边学边用就可以了,协同开发工具能用就可,需要深入再学不迟,只要了解分支开发等等基础内容就行了。然后配合github这个著名的交友网站(手动滑稽)就可以了,主要是用来保存自己的组件库代码,搭建组件库暂时还用不到,本地保存主要怕丢失了,所以云备份一份万无一失。 -
Node.js环境: 不会吧!不会吧!不会有人学前端还不知道
Node.js
吧, 好吧!其实我刚开始学也是不知道的,后面也是慢慢接触到,菜到自闭⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄,安装node
环境主要是用npm
包管理工具,npm
真是前端人的灵魂。Node.js下载地址,安装相关可以参考这篇博客。安装完成后推荐安装nrm
这个包,主要是用它换源贼方便,这里建议看看这篇博客(理直气壮夹带私货(。-`ω´-))。下图是我的node版本和npm版本:
-
vue&vue-cli: Vue是前端一个渐进式框架,vue-cli是一个项目构建工具,这里主要是用cli来构建一个基础的组件库项目,具体的细节就不做过多解释了。
-
注册npm一个账号: npm官网,注册账号就不用多说了吧,准备好一个邮箱,然后注册的时候记着注册名和密码,后面发布npm包会使用到。
-
小小建议: 公司让我尝试搭建一个公用的组件库,主要是前端一些代码复用率高,能抽成组件可以减少冗余,刚开始也是一脸迷茫,翻阅不少博客后才完成基本的搭建流程,期间也有看过element源码,当然不可能是完全啃源码,主要是饿了么这么优秀的vue开源ui组件库不看看源码,怎么对得起天天使用它٩(๑❛ᴗ❛๑)۶。主要是借鉴一下,整个项目的文件构建结构,然后组件构建的流程,大致能顺一下流程。最后再搭建组件库的过程中也确实对我有一定的帮助,所以建议大家也看看源码。(o°ω°o)
开始搭建组件库ヾ(≧∇≦*)ヾ
创建项目&调整文件名
查看vue-cli版本
搭建项目我使用的是 vue-cli的4+ 版本,node版本之前也有截图,cli最好是用 3+版本 。完成这些后,找一个保存项目的文件夹,然后使用cmd输入vue create xd-test-ui
就可以创建名为xd-test-ui
的项目了
创建项目
cmd输入vue create xd-test-ui
后会来到这个页面,一路回车默认就可了,这里我选择vue2
版本,剩下的是默认配置,是一些编译和拼写检测的配置,直接默认即可,如果想要深入了解,可以学习学习webpack
,这些配置完成后就进入安装页面,等待项目创建完成。
-
配置选项
-
安装过程
-
项目创建完成
可以看到构建完成后,最后提示使用npm run serve
运行,这是基础的vue-cli项目,当然这只是刚开始,完成组件库还需要进行进一步的"脱胎换骨"
┐( ̄ヮ ̄)┌。项目初始样子完成后,使用VsCode从项目根目录打开该项目。
调整文件夹命名
看了很多的博客,大家基本都是这个样子来修改的,包括element
源码里面的项目,也是有examples
文件夹(项目示例文件夹)和packages
文件夹(组件文件夹),所以这里随大流,将创建好的项目修改成如下的格式。
·
··
...
|-- examples // 原 src 目录,改成 examples 用作示例展示
|-- packages // 新增 packages 用于编写存放组件
...
··
·
- 修改文件名前后(src->examples,新增 packages)
项目配置调整
完成上述修改后,项目无法运行,需要调整配置,在 根目录 添加vue.config.js
文件,配置代码如下,vue.config.js
是vue-cli3
新增提供的一个可选配置文件,相关的配置链式操作可以查看官网的这篇配置介绍 webpack-chain,完成这些配置后项目就可以重新运行了。
//vue.config.js文件
const path = require('path')
module.exports = {
// 修改 pages 入口
pages: {
index: {
entry: 'examples/main.js', // 入口
template: 'public/index.html', // 模板
filename: 'index.html' // 输出文件
}
},
// 扩展 webpack 配置
chainWebpack: config => {
// @ 默认指向 src 目录,这里要改成 examples
// 另外也可以新增一个 ~ 指向 packages
config.resolve.alias
.set('@', path.resolve('examples'))
.set('~', path.resolve('packages'))
// 把 packages 和 examples 加入编译,因为新增的文件默认是不被 webpack 处理的
config.module
.rule('js')
.include.add(/packages/)
.end()
.include.add(/examples/)
.end()
.use('babel')
.loader('babel-loader')
.tap(options => {
// 修改它的选项...
return options
})
}
}
编写组件 φ(>ω<*)
组件目录构建
构建如下的文件目录格式,然后构建完成后就可以开始写代码了
|——
|——packages
| |——index.js
| |——button
| |——index.js
| |——src
| |——button.vue
|——
目前为止的目录截图。
组件代码编写
- button.vue文件内容
这里就是单个的组件文件,每个packages下的文件夹就是一个组件,这里是基础组件样式的编写。
<template>
<div>
<a :class="type">
<span></span>
<span></span>
<span></span>
<span></span>
<slot></slot>
</a>
</div>
</template>
<script>
export default {
name: "XdButton",
props: {
type: {
type: String,
default: "primary",
},
},
};
</script>
<style scoped>
@import url("https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
position: relative;
display: inline-block;
padding: 25px 30px;
margin: 40px 0;
color: #03e9f4;
text-decoration: none;
text-transform: uppercase;
transition: 0.5s;
letter-spacing: 4px;
overflow: hidden;
margin-right: 50px;
}
a:hover {
background: #03e9f4;
color: #050801;
box-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
0 0 200px #03e9f4;
-webkit-box-reflect: below 1px linear-gradient(transparent, #0005);
}
.warning {
filter: hue-rotate(300deg);
}
.success {
filter: hue-rotate(240deg);
}
a span {
position: absolute;
display: block;
}
a span:nth-child(1) {
top: 0;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, #03e9f4);
animation: animate1 1s linear infinite;
}
@keyframes animate1 {
0% {
left: -100%;
}
50%,
100% {
left: 100%;
}
}
a span:nth-child(2) {
top: -100%;
right: 0;
width: 2px;
height: 100%;
background: linear-gradient(180deg, transparent, #03e9f4);
animation: animate2 1s linear infinite;
animation-delay: 0.25s;
}
@keyframes animate2 {
0% {
top: -100%;
}
50%,
100% {
top: 100%;
}
}
a span:nth-child(3) {
bottom: 0;
right: 0;
width: 100%;
height: 2px;
background: linear-gradient(270deg, transparent, #03e9f4);
animation: animate3 1s linear infinite;
animation-delay: 0.5s;
}
@keyframes animate3 {
0% {
right: -100%;
}
50%,
100% {
right: 100%;
}
}
a span:nth-child(4) {
bottom: -100%;
left: 0;
width: 2px;
height: 100%;
background: linear-gradient(360deg, transparent, #03e9f4);
animation: animate4 1s linear infinite;
animation-delay: 0.75s;
}
@keyframes animate4 {
0% {
bottom: -100%;
}
50%,
100% {
bottom: 100%;
}
}
</style>
- button/index.js内容编写
如果要暴露组件,还需在组件文件夹内编写向外暴露组件的js文件
// 导入组件,组件必须声明 name
import Button from './src/button'
// 为组件提供 install 安装方法,供按需引入
Button.install = (Vue) => {
Vue.component(Button.name, Button)
}
// 默认导出组件
export default Button
- packages/index.js文件编写
在这里提供两种组件注册方式,一种是使用use
全部引入,另一种是按需引入组件,使用方法和elemnet
组件引用方法一样。目前只写了一种组件,所以两种引入的都一样。
import button from './button'
// 存储组件列表
const components = [
button
]
/*
定义install 方法,接收Vue作为参数,如果使用use注册插件,则所有的组件都将被注册
*/
const install = (Vue) => {
// 判断是否安装
if (install.installed) { return }
// 遍历所有组件
components.map(item => {
Vue.component(item.name, item)
})
}
//判断Vue初始化
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
install,
button
}
在组件库项目内引用组件(测试组件所用,可以跳过)
在examples/main.js
中全局注册组件,然后在examples/components/HelloWorld.vue
文件中编写使用按钮组件。
- main.js文件内容如下
import Vue from 'vue'
import App from './App.vue'
import XdUi from '../packages/index' //组件库项目内引入组件
Vue.use(XdUi); //全局注册组件
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
- 在HelloWorld.vue中的代码如下
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<XdButton>default</XdButton>
<xd-button type="primary">primary</xd-button>
<xd-button type="warning">warning</xd-button>
<xd-button type="success">success</xd-button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
这里我只是删除了一些组件库项目的默认内容,然后在这个页面中测试我编写的组件,在项目内测试,以防上传组件库后发现错误再折腾回来修改。
- 组件引用效果截图
组件打包
package.json文件编写
- name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
- version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
- description: 描述。
- main: 入口文件,该字段需指向我们最终编译后的包文件。
- keyword:关键字,以空格分离希望用户最终搜索的词。
- author:作者
- private:是否私有,需要修改为 false 才能发布到 npm
- license: 开源协议
以下为参考设置
···
"description": "基于Vue搭建的一个基础组件库。",
"main": "lib/xd-ui.umd.min.js",
"private": false,
"license": "MIT",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"lib": "vue-cli-service build --target lib --name xd-test-ui --dest lib packages/index.js"
},
···
-
编译为库的命令 lib 内容解析
- vue-cli-service build 构建包的命令
- –target: 构建目标,默认为应用模式。这里修改为 lib 启用库模式。
- –name:指定编译后的组件文件名字。
- –dest : 输出目录,修改为lib。
- 最后一个参数为入口文件,默认为 src/App.vue。这里我们指定编译 packages/ 组件库目录。
-
打包后图示说明
打包命令:npm run lib
上传到npm官网 罒ω罒
终于到了“鸡冻”人心的一步了,发布正式的npm包,然而到这里还需要在发布前做一些准备工作。
- 添加.npmignore文件
上传到npm
当然只需要一个构建好的lib
和相关的几个文件就足够了,这样别人引入的时候体积小,也不用获取多余的文件,就像上传到github
不需要node_modules
文件夹一样,因为这些东西太大,而且没有必要上传,所以这里在根目录添加.npmignore
文件,在里面写入忽略上传的文件夹和文件即可。
以下是参考配置:
# 这是复制 .gitignore 里面的
.DS_Store
node_modules
/dist
# 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*
# 以下是新增的
# 要忽略目录和指定文件
examples/
packages/
public/
vue.config.js
babel.config.js
*.map
*.html
-
登录到npm
- 首先需要到 npm 上注册一个账号,注意验证邮箱,不然之后会发布不了。
- 如果配置了淘宝镜像,先设置回npm镜像。
- 在控台输入
npm config set registry http://registry.npmjs.org
切换源 - 或者使用
nrm use npm
当然需要安装NRM,前面说过了。
- 在控台输入
- 然后使用
npm login
登录,输入之前注册的信息。 - 最后使用
npm publish
发布包,好耶!ヽ(゚∀゚)メ(゚∀゚)ノ 终于发布了第一个自己的包了。可以看到包的版本是0.1.0
,后续再发布包需要修改成和历史不同的版本号。如果发布成功,npm会使用邮件通知你,可以在邮箱中查看到自己的发布包成功的消息。 - 登录到npm官网查看自己发布的包
到这一步我们就完成了整个基于vue的npm包发布的流程,完成了第一个组件库的搭建,如果你成功了,哦耶!恭喜你!!!如果没有成功可能是版本或者某些配置遗漏了,可以回过头去看看,或者 重新来一次ヽ(・ω・´メ)(不要打我)。到这里基本就完成了组件库的搭建,好累啊啊啊!!!
新建项目引入安装自己的npm包测试 ❥(ゝω・✿ฺ)
当然如果要完成整个流程,那肯定得新建项目测试一下自己的包是否能用。
-
构建新的项目
vue create 项目名
。 -
使用
npm i xd-test-ui
安装上传的npm包。 -
确认检查包是否安装了。
-
在新项目中挂载下载好的组件。
import XdUi from "xd-test-ui" //引入组件
import "xd-test-ui/lib/xd-test-ui.css" //之前在组件库项目中没有引入,因为是一个项目,而新项目需要引入css文件才会有样式。
Vue.use(XdUi); //全局注册组件
- 在页面内编写引入的组件
<XdButton>默认</XdButton>
<xd-button type="primary">指定默认样式</xd-button>
<xd-button type="warning">警告样式</xd-button>
<xd-button type="success">成功样式</xd-button>
- 效果展示
好了,这里就万无一失的确认组件ok,引入没有问题,npm组件库完全的完成了,可喜可贺,可喜可贺!\\\٩(‘ω’)و////
项目地址✧⁺⸜(●˙▾˙●)⸝⁺✧
npm包地址
在项目中使用 npm i xd-test-ui
引入,然后和上述的方法一样引入即可。
github仓库地址
使用git clone https://github.com/ZERO-DG/xd-test-ui.git
下载项目。求个Star
gitee仓库地址
使用git clone https://gitee.com/zero-dg/xd-test-ui.git
下载项目。
参考大佬的博客
以上大佬部分先后顺序,本博客有部分借鉴的地方,全部来自于以上博客,感谢各位大佬!