汤小梦
https://juejin.im/post/5e200ee86fb9a02fdd38986d
不知不觉马上就要放假了,写一篇文章祝愿 2020 越来越好!
如今前端工程师的要求越来越高了,需要掌握的技术点越来越多了,会一些基本的前端技能完全适应不了快速变化的前端领域了。接下来我将从零实现一个自己的UI组件库并发布到npm上,提供给需要的朋友参考也总结下自己对封装组件的理解方便以后复习。本项目以button
按钮为例,详细的记录一下封装一个Button UI组件每一个步骤以及需要注意的地方:
需要掌握 Vue 的基本语法
组件之间的通信
插槽的用法
vue-cli3 创建项目、打包
npm & git 的用法
检查 node 环境配置
先本地全局安装node环境,vue的运行是依赖于node
的npm
的管理工具来实现的,node下载地址。下载好node之后,打开cmd管理工具,输入node -v
,回车,查看node版本号,出现版本号则说明安装成功,注意:node 的版本要在 8.9 或更高版本 (推荐 8.11.0+)
node -v npm -v
Vue 版本
关于旧版本
如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它, Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。
安装新版本
npm install -g @vue/cli
# OR
yarn global add @vue/cli
查看版本
vue --version | vue -V
创建项目
vue create mc-ui
OR
vue ui 也可以使用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
由于Element UI中的样式采用Sass,所以我们选择第一项即可 为什么不选择第二项呢?因为dart-sass比node-sass更好下载
选择代码风格
ESLint with error prevention only
ESLint + Airbnb config
ESLint + Standard config
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。回车后,系统会自动帮我们把选择的配置集成到模板中,然后生成一个完整的项目。
我们大致按照Element UI的 源码 目录进行我们自己的UI库项目开发。所以删除系统自动为我们创建的src、assets等目录,在根目录中创建一个packages目录用来存放我们要开发的UI组件;在根目录创建一个test目录用于测试我们自己开发的UI组件。由于我们更改了原项目的目录结构,使得系统本地运行以及打包找不到对应的目录,我们需要在项目的根目录中创建一个vue.config.js文件夹手动的去修改webpack配置,使得系统本地运行和打包正常。
// vue.config.js
const path = require('path');
module.exports = {
pages: {
index: {
entry: 'test/main.js',
template: 'public/index.html',
filename: 'index.html'
}
},
chainWebpack: config => {
config.module
.rule('js')
.include.add(path.resolve(__dirname, 'packages')).end()
.use('babel')
.loader('babel-loader')
.tap(options => {
return options;
})
}
}
基础
的实现
注意:为什么要在slot插槽外面加个span标签呢?为了美观,每个自定义button组件间相互有点间距????
export default {
name: 'McButton'
}
注意:组件中填写name属性,是为了封装组件提供install方法时,动态获取每个组件名进行组件注册
.mc-button {
box-sizing: border-box;
outline: none;
margin: 0;
transition: 0.1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
....
}
注意:user-select
属于CSS3
的属性,值为none表示禁止用户选中文字
效果
基础
的实现
常见的类型有:primary / success / warning / danger / info / text
注意:为什么绑定class时采用数组形式,而不用对象形式,因为会有多个动态绑定的属性,且使用对象的形式,这样就只有数组里可以放多个动态属性,且属性可以为对象
props: {
type: {
type: String,
default: 'default'
}
}
注意:这里接收属性为什么不用数组的形式?因为我们是封装组件给别人用的,所以要限制一些条件,不能让用户随意的输入
该功能时,样式没有改动
效果
基础
的实现
注意:为什么绑定class时采用数组形式,而不用对象形式,因为会有多个动态绑定的属性,且使用对象的形式,这样就只有数组里可以放多个动态属性,且属性可以为对象
plain: {
type: Boolean,
default: false
}
&.is-plain:hover,
&.is-plain:focus {
background: #fff;
border-color: #409eff;
color: #409eff;
}
效果
基础
的实现
round: {
type: Boolean,
default: false
}
&.is-round {
border-radius: 20px;
padding: 12px 23px;
}
效果
基础
的实现
circle: {
type: Boolean,
default: false
}
&.is-circle {
border-radius: 50%;
padding: 12px;
}
效果
基础
的实现
disabled: {
type: Boolean,
default: false
}
注意:添加是否被禁用时有两个作用:第一、让用户不能点击;第二、改变按钮样式 3. 效果
基础
的实现
icon: {
type: String,
default: ''
}
.mc-button [class*=mc-icon-]+span {
margin-left: 5px;
}
i标签上加v-if的目的:让用户即可以上传图标也可以上传文字或者上传文字和图标
注意:既传图标也传文字的话,图标和文字隔的很近,我们需要特殊处理下; 但是如果特性处理的话,单独的图标会不居中显示;所以我们要使用$slots获取包含有插槽的才让其显示处理
效果
基础
的实现
methods: {
handleClick (e) {
this.$emit('click', e) // 向父组件派发一个click事件,e表示携带的参数
}
}
效果
在Vue-cli3的 官方文档 中有个构建目标
有明确的说明怎么打包成一个应用或者一个库!此时,我们需要在package.json中添加一条打包命令
vue-cli-service build --target lib 指定打包的文件
然后控制台执行yarn lib
即可将我们的组件库包括字体图标一起打包生成一个dist文件夹
将代码上传到github
首先登录github 官网 创建一个新的仓库,然后复制新仓库的git地址。然后在我们本地创建的项目根目录执行git init,初始化git,然后再终端执行以下命令:
git remote add origin
git add .
git commit -am ":rocket: project init"
git push -u origin master
大家有没有发现我提交的commit不一样,其实就是用到了gitmoji这个依赖而已,简单说下他的用法:
全局安装这个依赖 npm install -g gitmoji-cli
commit 提交代码时,加上表情符号就好。例如:":bug: xxxx", 这样你提交的代码注释前面就会加一个emoji图标,很炫酷的哦,小伙伴们可以试一下????
常见的emoji有::art: 、 :ambulance: 、:lipstick:等等
将代码发布到npm
由于我们开发的组件库是给别人用的,我们没有必要把所有的代码都发布到npm上。所以我们需要在项目的根目录创建一个.npmignore的文件,忽略那些文件上传
// .npmignore
# 忽略目录test/
packages/
public/
# 忽略指定文件
vue.config.js
babel.config.js
*.map
.editorconfig.js
注意:由于我们要上传到npm上,所以我们本地npm的源要使用npm的源,不能使用淘宝源或其他的。查看一下本地电脑所有的源:
一切准备工作做好后,打开终端,执行npm login进行登录
登录
执行npm login命令,系统会提示输入账户和密码。如果没有npm账户,请注册 → npm官网
发布
若账户登录成功后,就可以再次执行 npm publish 进行发布
注意
一定要在package.json的scripts中添加main方便其他人下载时找到对应打包的文件
上传到npm上时,要将package.json中的private属性值改为false
修改源码后发布到npm时一定要更改项目的版本号
相信只要从头看到尾的小伙伴就会发现,封装一个组件很容易,主要的工作在于CSS样式上。只要自己有时间,然后根据像Element、iView、Antd等优秀的第三方UI库的源码,也可以实现一套属于自己的UI库。不管是面试还是自己公司内部需要搭建自己的UI库,只要小伙伴们掌握了封装组件的原理,其他的都问题不大。希望有需要的小伙伴手动敲一遍,加深对封装组件的过程。????加油
完
点个【在看】,或者分享转发,让更多的人也能看到这篇内容
关注公众号【全栈前端精选】,不定期分享原创&精品技术文章。
公众号内回复:【 1 】。加入全栈前端精选公众号交流群。
欢迎评论区留下你的精彩评论~
觉得文章不错可以分享到朋友圈让更多的小伙伴看到哦~
客官!在看一下呗