前端进阶-UI组件库

167 阅读5分钟

目的

  • 封装常见的功能性组件(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