一、项目简介
这是第一届【字节青训营】-走进前端的大作业,目前已开源到github上——lucky-fairys-lucky-draw
- ?实现抽奖前端页面,用JS模拟出抽奖过程;
- ?可以手工设置奖品池,每个奖品的中奖概率,起始矿石数和每次抽奖耗费的矿石数;
- ?完成抽奖后,给出中奖结果,多次抽奖,显示中奖列表;
其实就是仿掘金的抽奖程序,只不过它的应用场景除了适用C端用户的抽奖以外,还适用B端业务人员的配置。
二、涉及技术&知识点
这个项目涉及的知识内容有哪些?
从总体上看的话使用的语言分布在JS、HTML、SCSS上。
我感觉最吸引人的可能是我用到了字节开发的轻服务进行部署。?轻服务-5分钟快速构建应用
为什么选择这项技术而不是其他的?
把这个宏观的问题展开一下就是:
1. 为什么用SCSS而不用传统的CSS开发?
2. 为什么用JavaScript而不用其它?
3. 为什么用轻服务进行部署?
首先,为什么用SCSS而不用传统的CSS开发?
就个人使用感而言,SCSS(实际上它叫SASS,只是文件名后缀是.scss)在排版管理上非常方便。
传统CSS的代码是这样写的:
main .luckyGridView .container .gift img {
width: 64px;
}
main .luckyGridView .container .luckyDraw {
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
}
main .luckyGridView .container .luckyDraw:active {
transform: scale(0.98);
}
复制代码
SCSS的代码是这样写的:
main {
.luckyGridView {
.container {
.gift {
img {
width: 64px;
}
}
.luckyDraw {
display: flex;
justify-content: center;
align-content: center;
flex-wrap: wrap;
&:active {
transform: scale(0.98);
}
}
}
}
}
复制代码
咋一看SCSS使用了嵌套结构好像还挺复杂,但实际使用上非常方便,比如说我后面要加新的类或者标签的话,只要找到它的上层层级并判断它是属于兄弟元素还是子类元素就能确定它的位置。
结合VSCode上的插件Live Sass Compiler,它就能够帮你转换CSS文件,所以本质上还是使用的是CSS文件,只不过在开发阶段我们用的是SASS而已。
由SCSS编译而来的CSS文件长这样:
而且在这次项目中我只是浅略的使用了SASS的优势,更多优势可以查看它的官网。
其次,为什么用JavaScript而不用其它?
因为当前不是什么复杂的功能,也不涉及到用户数据管理,使用JS开发特别方便而且很考验基本功,后期会考虑转成React或Vue。
最后,为什么用轻服务进行部署?
选择轻服务的优势真的非常大!它就像你的全职管家一样给你配置好了一切,我可以不用买服务器就能上线网站、不用选数据库就能设计表格设计接口、不用学NodeJS(以后还是要学的…)就能在服务器上使用JS。不过目前还在优化阶段,这也是我使用JavaScript的直接原因,保证最稳定的部署。
三、实践过程
这个项目的搭建思路是什么?
主要是面向对象是开发思想,比如和奖池有关的函数我都建了一个叫Gifts
的类写在里面,连接后台DB也根据表格名进行分类,这类文件我都放到了modules文件夹下。
剩下的就是通用方法common.js
和在index.js
文件里去写调用这些方法的主逻辑。
因为首页是分角色进行管理,一个是player角色,一个是creator角色(因为比较有趣就这样命名了),所以它的主方法也被分为两类。
实践过程中遇到了哪些问题?如何解决的?
怎样上传图片,用URL.createObjectURL
还是FileReader
?
经过两个方案的实践对比后,最终使用的是FileReader
,将图片的二进制内容转成base64,用普通的Post方法上传到后端。
最后达成怎样的效果?可以如何进行优化提升?
最终效果就是能显示后台存放的图片数据,因为我存的是svg文件非常的小,所以没进行优化。如果存的是JPG,PNG呢?后面我会进行相应的优化升级。
四、总结思考
这个项目中最令自己自豪的细节是什么?
1.运用了7的二进制代码是111的优势
这样任何数与7进行&运算都会在[0,7]这个区间,非常适合模拟九宫格抽奖的过程。
2.把日期格式转换提炼成了非常优雅的通用方法,在以后的项目中可以直接复用。
const formatterMap = {
YYYY: (date) => date.getFullYear(),
MM: (date) => date.getMonth() + 1,
DD: (date) => date.getDate(),
HH: (date) => date.getHours(),
mm: (date) => date.getMinutes(),
ss: (date) => date.getSeconds(),
}
// 时间格式变换
export const dateFormatter = (date, str) => {
Object.keys(formatterMap).forEach((format) => {
str = str.replaceAll(format, formatterMap[format](date));
});
return str;
}
复制代码
// 外部调用
import { dateFormatter } from "../common.js";
...
const dateFormattedStr = dateFormatter(
date,
"YYYY年MM月DD日 HH时mm分ss秒"
);
li.innerText = `获得了${value},${dateFormattedStr}`;
复制代码
3.用Promise.all一次发送请求
class Images {
...
const tasks = this.file.map(
(file, i) => new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (e) => {
this.urls[i] = e.target.result;
resolve();
}
})
);
await Promise.all(tasks);
return this.urls;
}
复制代码
4.在用户体验上,因为进去页面得等待后台发送数据,我使用了加载动画效果
随着百分比的值越大,越能揭开抽奖画面的“面纱”。
其它想到再补充
这个项目在未来还有哪些改进优化的空间?
1.可以继续完善登录页面,比如真正是账户密码登录,并且做权限管理;
2.点击抽奖得出结果时不要用简陋的alert
弹框,因为这样会和报错一样,导致用户体验感不佳;
3.发送请求可以继续优化,发送请求数量尽量少;
4.预览图片直接用的input[type='file']
,实际上应该把它隐藏,用显式的a标签调用它,这样方便更好的设计好看的CSS样式,直接对input[type='file']
进行CSS样式设计实在太局限了。
和其他同学的解决方案相比,我的方案有哪些优势或者不足?
优势:用了轻服务
不足:没有使用现在流行的框架
五、 引用参考
stevenjoezhang/live2d-widget-把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platform
bradtraversy/50projects50days/blurry-loading-50+ mini web projects using HTML, CSS & JS