本人在一个创业公司负责全部的前端工作,所以说是光杆司令也颇为合理。
2023是我入职后的第一年,也是前端正式工作的第一年
去年年底左右结束实习,入职后写了一些React,之后马上就开始创建小程序的项目。
对于我来说可以写用户端这件事情,还是很令人兴奋的,毕竟可以写出漂亮的东西了。相信这也是每一个前端开发同学曾经的梦想,那就是写出来优美的页面。
历时将近一年的小程序项目
从0到一的开发了这个电商小程序,考虑到没有跨端需求,所以采用了原生开发
着手封装网络请求
项目使用了一个将微信API封装为支持异步使用的库wx-promise-pro,这样就可以优雅的使用异步调用微信的api了,简单的封装了一下网络请求。
考虑到页面样式并不通用,所以并未添加UI组件库。
自己封装的一些组件会参考借鉴Vant UI
我认为Vant相对成熟一些,也想知道对于特殊样式或功能,vantUI使用的是自己实现还是二次封装的微信API
其实Vant的源码看起来还是相对简单的。我有一些功能会将它的源码简化一下,封装到自己的里面,例如计时器、弹出框、树形选择框、骨架屏这些。
总体来看封装组件奉行几个思想
- 单一职责原则
理论上来说组件应该只负责一种功能,有着单一明确的职责,有利于降低代码复杂度,提升组件的可维护性。
另一方面,我认为它和类在设计上比较相似,封装特定的功能、模块,提供清晰明确的目标。
- 可配置性
提供适当的配置选项,使得组件可以适应不同的用例。包括属性、事件、样式等的配置。参考组件库中的这些配置来进行封装就好了。
- 样式隔离
不想用CSS in JS来处理样式隔离的时候,可以采用简单的前缀命名
如果你不想重复写前缀可以在小程序中搭配wxs语法使用来为wxml文件中的类名添加前缀,并使用less语法&来为css样式类名添加前缀
<wxs module="text">
module.exports = {
classAdd: function (name) {
return 'van-' + name
}
}
</wxs>
<view class="{{text.classAdd('title')}}">
<view class="{{text.classAdd('title')}}__label">
</view>
</view>
.van-title {
color: rgb(var(--color-6));
&__label {
font-size: var(--title-1)px;
}
}
- 完善的文档
虽然我们的用户可能大多数会懂这些封装的组件,但是一个完善的文档会让人更快更准确的了解到这个组件的作用,背景,可能不需要多正式,最简单的就是在组件的文件夹中创建 README.md
- 自由发挥的一些性能、组件通信
这些和你的业务有关了,一些业务相关组件需要去封装一些复用的业务逻辑,这类业务组件更加需要文档来帮助其他人理解。
了解CSS动画
没有做过CSS动画的时候,可能对这个名词有一些遥望此山高的感觉。
但其实动画很简单,只需要分解一下目标效果的轨迹、时间和变化方式(放大、旋转、拉伸)这些基本动作。
常用来做动画的两个属性
- animation
定义一个帧动画,通过关键帧来指定动画在每个时刻的样式。可以定义动画的持续时间、播放次数、延迟时间、缓动函数等
animation配合transform使用可以生成绝大部分动画,例如旋转一个元素。
// 首次等待5s后 在1s内 匀速 旋转 360度 无限重复旋转的操作
.box {
animation: light 1s linear forwards 5s;
}
@keyframes light {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
(我们经常听到开启硬件加速来优化动画,其实我们使用transform就算是优化了,它可以替代比如margin这种用来布局的属性。)
- transition
可以让一个或多个属性的变化在一段时间内平滑地过渡。可以定义过渡的持续时间、延迟时间、缓动函数等
transition主要应用元素的状态发生改变时,例如从未选中变为选中态,使其高亮过渡的更平滑。
这两个属性基本可以全部覆盖一般的业务需求了。
一个工具型的小程序
是用来处理订单的分拣打包配送的小程序,主要涉及了一些文件图片等信息的上传。
监听图片、文件上传腾讯云
对于上传文件和图片这里我写了一个behavior,它让我不用关心图片上传到云存储的逻辑,只需要管理用户上传的数据就好了。
- 上传操作:监听了file文件列表,用户上传时设置状态为0,触发监听后将状态为0的对象做上传操作,并设置上传中的状态,上传成功后更新上传成功状态。
- 页面显示:image组件显示本地路径图片,用户无需等待上传完成即可查看图片
import { fetchGetUrl } from "xxxx"
module.exports = Behavior({
observers: {
// 监听imgList(可以自定义,我项目中的图片数组都用的这个字段)
imgList: function (imgList) {
imgList && Array.isArray(imgList) && imgList.map((item, idx) => {
if (item.upStatus === 0) {
this.upLoadImg(idx)
}
})
}
},
methods: {
upLoadImg(index) {
const originUrl = this.data.imgList[index].originUrl;
this.setData({
[`imgList[${index}].upStatus`]: 1
})
const fileExtension = originUrl.indexOf('.') > -1 ? originUrl.split('.').pop() : '';
// 获取云存储上传链接
fetchGetUrl({ bucket: "IMG", extension: fileExtension }).then((res) => {
const regex = /(.*?)\?/;
const matches = res.match(regex);
//触发上传函数
putFile(originUrl, res).then(res => {
if (res.statusCode !== 200) {
wx.showModal({ title: '上传失败', content: JSON.stringify(res), showCancel: false });
this.setData({
[`imgList[${index}].upStatus`]: 3
})
}
this.setData({
[`imgList[${index}].upStatus`]: 2,
[`imgList[${index}].cosUrl`]: matches[1]
})
})
})
}
}
})
// putFile函数传入拍照或上传后生成的临时链接 和 上传的腾讯云链接
const putFile = async function (filePath, url) {
var wxfs = wx.getFileSystemManager();
try {
let fileRes
try {
fileRes = wxfs.readFileSync(filePath);
} catch (error) {
wx.showToast({
title: '读取文件失败',
icon: 'none'
})
}
const res = await wx.pro.request({
url: url,
method: 'PUT',
header: {
'content-type': 'image/' + filePath.split('.')[1]
},
data: fileRes,
})
return res
} catch (error) {
return Promise.reject(error)
}
};
过程中中也遇到许多小程序的问题,例如隐私收集、位置授权、小程序本身未修复的bug等等导致的问题。都算按部就班的解决了。