handy-ui是一个基于React hook开发的组件库,兼容移动端,用于个人对前端技术和交互设计的学习与探索、及工作上的需求
仅供参考,暂时不建议在正式项目中使用
-
基础组件
- button 按钮
- cell 单元格
- icon 图标
- popup 弹出层
- toast 轻提示
- menu 目录
- image 图片
- style 内置样式
-
表单组件
- field 输入框
- radio 单选框
- checkbox 复选框
- picker 选择器
- calendar 日历
- datePicker 日期选择器
- uploader 文件上传
- rate 评分
- stepper 进步器
- switch 开关
- searchBar 搜索栏
-
反馈组件
- Loading 加载
- actionSheet 动作面板
- dialog 弹出框
- dropdownMenu 下拉菜单
-
展示组件
- carousel 轮播
- skeleton 骨架屏
- backToTop 返回顶部
- drag 拖拽
- imagePreview 图片预览
-
导航组件
- tabs 标签页
- sidebar 侧边导航
- 无缝轮播:当切换到最后一个轮播图时,如何悄无声息回到第一张
核心思想:
1)把第一张图复制并push到最后一个位置,复制之前的最后一张图并unshift到第一个位置
2)在div上绑定transitionend事件,用来监听CSS完成过渡后触发,
2.1)当切换到最后一张图时,马上在回调事件上设置第一张(transform),把currentIndex设置为0
2.2)当切换上一张,到达第一张时,马上在回调事件上设置回到最后一张,把current设置为length-1
<!--vant的思路:不额外创建dom,而是判断将要切换到第一张或最后一张时加transform-->
<div style="width: 1440px; transition-duration: 500ms; transform: translateX(-1440px);">
<div style="width: 360px; transform: translateX(1440px);">1</div>
<div style="width: 360px;">2</div>
<div style="width: 360px;">3</div>
<div style="width: 360px;">4</div>
<!-- 切换到第一张时
<div class="van-swipe-item" style="width: 360px; transform: translateX(1440px);">4</div>
-->
</div>
- 自动播放
- 加手势切换
优化点:
- 使用useMemo(记忆计算结果)和useCallback(记忆函数体)都会在组件第一次渲染的时候执行,之后会在其依赖的变量发生改变时再次执行;
- 定时器中,使用setState的函数模式解决setState时数据不实时更新问题
可以用ui组件当作骨架屏,可以用[loader]或者plugin来实现
ui组件思路:用div作为占位符,相当于用图片代替
loader思路:
1)babylon解释器把代码字符串转化为AST树
2)babel-traverse对AST树进行解析遍历出整个树的path(在这里可以对代码进行改造)
3)plugin转换出新的AST树
4)输出新的代码字符串
plugin思路:
起个服务器访问页面,把内容抓下来转成骨架屏的元素,然后把改造的dom元素变成html内容,替换到 <div id ='root'><!--shell--></div>
里
使用:将loading属性设置成false表示内容加载完成,此时会隐藏占位图,并显示Skeleton的组件
1)监听input file的change事件,获取到file对象<input type="file" @change="handleFileChange" />
2)把这个对象通过file.slice切割成chunk[0: {file: Blob} 1: {file: Blob}...]
3)使用spark-md5.js,给每个切片文件按顺序生成md5名称 (另开一个worker线程生成)
3)把每个chunk通过FormData上传到后台
3.1)上传前先请求校验,后台校验切片是否已经存在某个文件中(把hash和文件名传过去,判断文件中是否已有hash名),已存在返回false,为为存在返回true
3.2)new FormData()实例,把chunk和hash都append进去,提交上传请求,通过Promise.all并发请求
3.3)拿到请求返回的结果,计算 本次上传成功数量+之前上传的切片(暂停的情况) 是否等于 所有切换数量。
等于的话就发送合并请求,把切片合并一起,删除hash内存
const formData = new FormData()
formData.append('chunk', chunk) // Blob {size: 577542, type: ""}
formData.append('hash', hash) // 5530cc512e2a3ab0652b300f0cd2224c-0 分片的hash名称 -1/-2/-3/-4
formData.append('filename', state.container.file.name) // Web全栈工程师的自我修养.mobi
formData.append('fileHash', state.container.hash) // 5530cc512e2a3ab0652b300f0cd2224c hash名称
1)使用FileReader对象异步读取blob文件,将他转成base64
2)通过canvas元素使用一个2D上下文,drawImage绘制图片(传入图片/宽/高),通过canvas.toDataURL转化为base64(传入压缩质量,重点)
3)atob解析base64转换为byte,再用ArrayBuffer转为二进制
4)通过new File实例一个blob对象,append到FormData上,用于上传到服务器
// 核心代码
ctx.drawImage(img, 0, 0, 200, 200);
const imageDataURL = canvas.toDataURL(fileObj.type ||'image/jpeg', pictureQuality);