小游戏练习
游戏主要分成两个:gameA和gameB
整个过程主要分为三部分:
首页:
主要内容:游戏难度分成三个等级,改变变量level的具体数值,传给gameA和gameB两个页面。
重点:
1.在src文件夹中创建一个新的文件夹models,使用useModel,创建一个全局变量level,所有页面均可以使用。
2.按钮点击样式的修改,使用:hover,对于点击的按钮有颜色的浮动变化。
gameA:
主要内容:在移动对象中添加图片,对目标图片进行计数。
重点:
1.使用useEffect对目标函数进行监听,可以针对不同函数做出相应操作。注意监听的目标和顺序,当顺序不合适的时候,会产生死循环。
useEffect(() => {
console.log(forRun.animationTime);
if (forRun.styleVar && forRun.styleVar.transition) {
setForRun({ ...forRun, playState: true });
setTimeout(() => {
askUser();
setForRun({ ...forRun, playState: false, styleVar: { ...defaultStyle } });
}, forRun.animationTime * 1000 + 1000);
}
}, [forRun.styleVar]);
2.利用transform和transition,使对象进行移动并固定移动时间。
styleVar: {
height: '100px',
transition: `all ${forRun.animationTime}s linear`,
transform: `translateX(${-1 * imageParamListItemWidth * imageParamList.length}px )`,
},
3.使用window.prompt(),可以在弹窗中输入数据。
const alertInput = window.prompt('请输入看到的白底成年女性头像数量!');
4.取固定范围的随机数
const randomNum = (max: number, min: number) => {
const num = Math.floor(Math.random() * (max - min + 1)) + min;
return num;
};
5.对数组内元素进行渲染
{item.map((status, index) => ())}
gameB:
主要内容:在固定范围内,截取图片。
重点:
1.对图片进行重现达到截图的效果
2.计算图片运行距离:
const endTime = new Date().valueOf();
const runTime = endTime - startTime;
const currentLength =
((areaWidth + pictureListItemWidth) / forRun.animationTime / 1000) * runTime;
let isOk: boolean;
if (level === 1) {
isOk = currentLength >= 550 && currentLength <= 700;
} else if (level === 2) {
isOk = currentLength >= 575 && currentLength <= 675;
} else {
isOk = currentLength >= 600 && currentLength <= 650;
}
forRun.pictureState = isOk;
forRun.runLength = currentLength;
console.log(forRun.runLength, forRun.pictureState);
startTime = 0;
对图片在新的区域移动相同距离:
transform: `translateX(${1200 - forRun.runLength}px )`,
3.监听文档的enter事件,当此组件销毁时,enter事件删除
useEffect(() => {
document.addEventListener('keypress', handleEnterKey);
return () => {
document.removeEventListener('keypress', handleEnterKey);
};
}, [handleEnterKey]);
4.监听键盘事件,按下enter,判断当前是否接收回车按键(a && b),记录按键时间,对数据进行处理,阻止本次播放过程中再次按键。同时为了避免在图片移动时不必要的更新,使useCallback:
const handleEnterKey = useCallback(
(e: KeyboardEvent) => {if (e.code === 'Enter' && startTime != 0) {}
else{startTakePictures()}}
5.初始样式的类型设为:
styleVar: Record;
pictureStyle: Record
6.对state进行setState的时机要判断清楚,不是state有变化了就马上进行set,根据当前情况,如果后续还有其他变化,不需要立即进行setState,还可能产生关联的state一直在改变的情况,就容易出现死循环,可以在确定没有多于变化的时机,在进行一次set,达到整体刷新的结果。
难度第二级
难度第三级
页面布局:
首先在config.ts文件中,将layout取消使用,那么项目原本的布局就不再使用。
export default defineConfig({
hash: true,
antd: {},
dva: {
hmr: true,
},
layout: false,
在src文件夹中创建一个新的文件夹layouts,在路由文件中,使用新的布局文件。
创建BasicLayout文件:
const { children } = props;
return (
<>
{children}
>
);
优化:
1.鉴于gameB图片运行速度过快,将start按钮取消,换成由enter控制开始和结束。根据code和图片开始时间的有无进行判断。
2.具有相同状态的变量归纳到同一个变量中进行控制。
3.css文件的优化,具有相同样式的进行合并。
总结
1.对useState,useEffect,useModel,table中item的元素渲染等印象深刻,熟练度提高,对代码顺序的严谨提高重视,防止死循环出现。
2.页面布局:灵活使用模板自带的布局,可以套用加以修改。注意route的实际意义,在相对应的route页面添加或修改,不要在config页面做多于修改。
3.提高对JavaScript的认识和理解,熟记常见语法,常见函数。
4.增加对各类样式的熟悉度,针对不同样式需求,可以有多种方式实现。
5.在搭建页面时注意变量初始化,锻炼统筹思想,在进行方法详细编写之前,把所需要的变量,函数,常量等参数准备好,后续直接使用,不要出现边写边增加变量的现象,在结尾整理时,容易出现变量或者函数之间互相影响,产生预料之外的变化和错误。