目的
- 封装常见的功能性组件(Button,Modal,Form相关)
- 把组件封装成UI组件库并且发布到NPM上
涉及的知识点
- vue 基础语法
- 组件基本语法
- 组件通讯(sync,provide,inject)
- 插槽的使用
- props校验
- 过渡与动画处理
- 计算属性与监听属性
- v-model语法糖
- vue插件机制
- npm 发布
收获
- 掌握组件封装的语法和技巧
- 学会造轮子,了解element-ui组件库的实现原理
- 搭建和积累自己的组件库
button组件
参数支持
- type
- plain
- round
- circle
- disabled
- icon
事件支持
- click 点击事件
开始
//禁止元素的文字被选中
-moz-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
- type 属性 让按钮有不同的样式,我们只需要控制类名就可以
:class="[`ak-button-$(type)`]"
- 图标 阿里图标自己下载一套
// 每个图标类名都需要
.ak-icon 改成
属性选择器
[class *= 'ak-icon-']
这样真的方便使用吗?属性选择器,而且这个全局的,不会都遍历一遍吧
我觉得还是用之前的吧
相邻选择器 选择紧连着另一元素后的元素,二者具有相同的父元素。只会选择的一个相邻的匹配元素
.ak-button [class*='ak-icon-'] + span {
margin-left: 5px;
}
this.slots 打印所有插槽 传了值都有一个默认的default
Dialog 组件
知识
- vue过渡动画
- sync 修饰符
- 具名插槽与v-slot指令
参数支持
- title
- width
- top
- visible
事件支持
- opened 模态框显示的事件
- closed 模态框关闭的事件
开始
- 具名插槽现在
<template v-slot:title></template>
$slots.footer 有就显示,没有就不显示
@click.self = "handleClose"
只有点击自己才执行 这个遮罩层
sync修饰符,我不想子传父,然后父组件还要注册一个事件才能够改变。这时需要sync
- sync 修饰符的使用
触发的父组件的事件就叫 update:money
但是我们直接用修饰符.sync 来修饰 :money.sync = "money"
在内部会帮我们做@update:money = "func" 接收值并且修改值
- 动画的使用
.ak-enter{ opacity:0; }
.ak-enter-to{ opacity:1; }
.ak-enter-active{ transition:all .5s; }
.ak-leave{ opacity:1; }
.ak-leave-to{ opacity:0; }
.ak-leave-active{ transition:all .5s; }
// 这种方式有点类名多
然后使用动画的方式
.ak-enter-active{ animate:akAnimate .5s }
.ak-enter-active{ animate:akAnimate .5s reverse} 反过来
@keyframes akAnimate {
0% {},
100% {},
}
- scoped 原理 加上scoped 之后会有一个属性选择器 v-229ee358 scoped 会给当前组件的模板中的所有的元素都添加一个随机的属性 scoped 会给当前组件中所有样式也添加一个对应的属性选择器
- 问题来了,footer的button组件是父组件传过来的,他的scoped跟当前组件随机的属性不一样 不加上scoped可以解决这个这个问题
- 深度选择器 scss里面的选择器 ::v-deep less--/deep/ css-->>> 组件库样式覆盖不了的时候 vue-loader
如果你希望scoped 样式中的一个选择器能够作用得"更深",例如影响子组件,你可以使用 >>> 操作
如何加了深度选择器,那么就不会加上随机的属性了
input 组件
参数支持
- placeholder
- type
- disabled
- clearable 是否显示清空按钮
- show-password 是否显示密码切换按钮
- name
事件支持
- blur
- chage
- focus
开始
- v-model
v-model实质上就是一个语法糖,等价于
<input type="text" v-model="username"
<input type="text" :value="username" @input="username=$event.target.vlaue"/>
这个$event要注意一下
怎么感觉和sync一样呢!就是会内部帮直接赋值
如何是双向的呢?单向是父传子(传了value属性),当父组件改变了value的值,那么子组件也会重新的渲染。反向是子传父这样就形成了双向数据绑定。
v-model 内部怎么知道我传的事件名是input 我不传input能不能呢?
- clearable 显示图标判断 子传父清楚value值
- showpassword 双重三元运算符去控制type的类型 text or password 先判断是否要显示showpassword icon ,然后在判断显示 双重三元判断
switch 组件
参数支持
- v-model
- name
- activeColor 自定义的激活颜色
- inactiveColor 自定义的不激活颜色
事件名称
- change change时触发的事件
开始
- this.$nextTick() 等待value发生改变了,根据value的值进行判断 返回promise 可以用then,也可以用async await
- name属性,因为是表单元素,一定不能丢了name 加个checkbox,然后定位隐藏起来
radio 组件
参数支持
- v-model
- label
- name
开始
- radio 是label作为值
- v-model 指向的作为选中的选框
- 是根据v-model 来进行分组的
发布 封装成UI组件库
-
创建新的项目
-
创建package文件夹(用于存放所有的组件)和examples(用于进行测试,把src改成examples)
-
修改配置项 vue.congfig.js
-
如何做成vue的插件 Vue.use(plugin) 安装vue.js插件。如果插件是一个对象,必须提供install方法。如果插件是一个函数,它会被作为install方法。install方法调用时,会将Vue作为参数传入
-
此时,我们需要在packages路径下,新建一个index.js文件,用于声明install对象。就是在main.js中调用Vue.use(Input)时,就会去这个index.js 里执行install。在目前我们是直接的全部install了,那如何是按需加载是不是要判断的是我们use加载的是哪个呢?
-
我们需要构建成库,所以我们在vue-cli官方文档中找到相应命令:vue-cli-service build --target lib 所以我们在package.json文件中的script下加入该条指令,并且命名为lib,需要注意的是,我们需要在打包指令后面加上需要打包的路径,这里我们指定为 packages/index.js 。
-
然后我们在终端中使用lib(npm run lib)命令就可以对packages/index.js指定的组件进行打包了。打包完成后,会默认生成一个名为dist的路径,我们的打包文件就在这个路径下。
-
组件库上传到npm 如果想把包发布到npm上,package.json中的private必须为fasle,我们需要将其设置位公有的包:"private": false, 同时我们可以指定入口文件 "main": "dist/one-ui-upload.umd.min.js"
"name": "aking-vue_ui",
"version": "0.1.2",
"private": false,
"main": "dist/aking-vue_ui.umd.min.js",
"author": "aking",
"license": "ISC",
"keywords": [
"aking",
"vue",
"ui"
],
- 第二步、根目录下增加一个.npmigore文件 这个文件的作用是将一些不需要上传到npm的路径、文件进行忽略,我们在上传到npm时就不会把这部分上传了。因为我们已经将项目打包好了,所以我们只用上传dist路径下的打包文件,不需要上传源码了。
# 忽略目录
examples/
packages/
public/
# 忽略指定文件
vue.config.js
babel.config.js
*.map
- 2.使用npm login 登录
- npm publish