},
“less-loader”
]
}
]
},
// 配置Webpack插件
plugins: [
new CleanWebpackPlugin(),
new HTMLWebpackPlugin({
// title: “这是一个自定义的title”
template: “./src/index.html”
}),
],
// 用来设置引用模块
resolve: {
extensions: [‘.ts’, ‘.js’]
},
mode:‘development’
};
-
新建
src
文件夹,创建index.ts
和index.html
-
src文件夹内,新增modules文件夹和style文件夹
2.编写结构和样式
src/index.html
src/style/index.less
//设置颜色变量
@bg-color:#b7d4a8;
- {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#main {
display: flex;
flex-flow: column;
align-items: center;
justify-content: space-around;
margin: 0 auto;
width: 360px;
height: 420px;
border: 10px solid #000;
background-color: @bg-color;
border-radius: 30px;
#stage{
position: relative;
width: 304px;
height: 304px;
border: 2px solid #000;
#snake{
&>div{
position: absolute;
width: 10px;
height: 10px;
background-color: #000;
border: 1px solid @bg-color;
}
}
&>#food{
display: flex;
flex-flow: row wrap;
justify-content: space-between;
align-content: space-between;
position: absolute;
top: 10px;
left: 10px;
width: 10px;
height: 10px;
&>div{
width: 4px;
height: 4px;
background: #000;
transform: rotate(45deg);
}
}
}
#score-panel{
width: 300px;
display: flex;
align-items: center;
justify-content: space-between;
}
}
body {
font:bold 20px “Courier”;
}
3.模块化
src/modules/Food.ts
class Food{
element:HTMLElement;
constructor(){
//this.element=document.getElementById(‘food’) as HTMLElement
this.element=document.getElementById(‘food’)!;
}
get X() {
return this.element.offsetLeft
}
get Y() {
return this.element.offsetTop
}
change() {
this.element.style.left=Math.ceil(Math.random()*29)*10+‘px’;
this.element.style.top=Math.ceil(Math.random()*29)*10+‘px’;
}
}
export default Food;
src/modules/ScorePanel.ts
class ScorePanel{
score:number=0;
level:number=1;
scoreEle:HTMLElement;
levelEle:HTMLElement;
maxLevel:number;
upScore:number;
constructor(maxLevel:number=10,upScore:number=10){
this.scoreEle= document.getElementById(‘score’)!;
this.levelEle= document.getElementById(‘level’)!;
this.maxLevel=maxLevel;
this.upScore = upScore;
}
addScore(){
this.score++;
this.scoreEle.innerHTML = this.score + ‘’;
if(this.score % this.upScore === 0){
this.levelUp();
}
}
levelUp(){
if(this.level<this.maxLevel){
this.levelEle.innerHTML = ++this.level + ‘’;
}
}
}
export default ScorePanel;
src/modules/Snake.ts
class Snake{
head:HTMLElement;
bodies:HTMLCollection;
element:HTMLElement;
constructor(){
this.element = document.getElementById(‘snake’)!;
this.head = document.querySelector(‘#snake>div’)!;
this.bodies=this.element.getElementsByTagName(‘div’)!;
}
public get X(){
return this.head.offsetLeft;
}
public get Y(){
return this.head.offsetTop;
}
set X(value:number){
if(this.X === value){
return;
}
if(value<0 || value>290){
throw new Error(‘蛇撞墙了!!’)
}
//是否掉头
if(this.bodies[1]&&(this.bodies[1] as HTMLElement).offsetLeft === value){
if(value>this.X){
//左走向右调头
value -= 20
}else{
value += 20
}
}
//移动身体
this.moveBody();
//移动蛇头
this.head.style.left = value + ‘px’;
this.checkHeadBody();
}
set Y(value:number){
if(this.Y === value){
return
}
if(value<0 || value>290){
throw new Error(‘蛇撞墙了!!’)
}
//是否掉头
if(this.bodies[1]&&(this.bodies[1] as HTMLElement).offsetTop === value){
if(value>this.Y){
//左走向右调头
value -= 20
}else{
value += 20
}
}
this.moveBody();
this.head.style.top = value + ‘px’;
this.checkHeadBody();
}
addBody(){
this.element.insertAdjacentElement(‘beforeend’,document.createElement(‘div’))
}
moveBody(){
//将后面身体的位置改为前面身体的位置,先改后面的位置,
//后面的位置依附前面的位置
for(let i = this.bodies.length-1;i>0;i–){
let X = (this.bodies[i-1] as HTMLElement).offsetLeft;
let Y = (this.bodies[i-1] as HTMLElement).offsetTop;
// 将值设置到当前身体上
(this.bodies[i] as HTMLElement).style.left = X + ‘px’;
(this.bodies[i] as HTMLElement).style.top = Y + ‘px’;
}
}
// 移动后检查
checkHeadBody(){
//获取所有身体坐标
for (let i = 1; i < this.bodies.length; i++) {
if(this.X === (this.bodies[i] as HTMLElement).offsetLeft &&this.Y === (this.bodies[i] as HTMLElement).offsetTop){
throw new Error(‘撞到自己了!’)
}
}
}
}
export default Snake
src/modules/GameControl.ts
import Food from “./Food”;
import ScorePanel from “./ScorePanel”;
import Snake from “./Snake”;
class GameControl{
snake:Snake;
food:Food;
scorePanel:ScorePanel;
//蛇的运动方向
direction:string=’ ';
//游戏是否结束
isLive = true;
constructor(){
this.snake = new Snake();
this.food = new Food();
this.scorePanel = new ScorePanel();
this.init();
this.run();
}
init(){
//绑定键盘事件
document.addEventListener(‘keydown’,this.keydownHandler.bind(this))
}
//键盘响应函数
//key:ArrowUp ArrowDown ArrowLeft ArrowRight
// IE: Up Down Left Right
keydownHandler(event:KeyboardEvent){
const keyhefa = [‘ArrowUp’,‘ArrowDown’,‘ArrowLeft’,‘ArrowRight’,‘Up’,‘Down’,‘Left’,‘Right’,’ ']
if (keyhefa.indexOf(event.key)>-1) {
this.direction = event.key;
}
}
//蛇移动的方法
run(){
//获取蛇现在的坐标
let X = this.snake.X;
let Y = this.snake.Y;
//修改位置变量
switch(this.direction){
case ‘ArrowUp’:
case ‘UP’:
Y -= 10;
break;
case ‘ArrowDown’:
case ‘Down’:
Y +=10;
break;
case ‘ArrowRight’:
case ‘Right’:
X += 10;
break;
case ‘ArrowLeft’:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
总结一下这三次面试下来我的经验是:
-
一定不要死记硬背,要理解原理,否则面试官一深入就会露馅!
-
代码能力一定要注重,尤其是很多原理性的代码(之前两次让我写过Node中间件,Promise.all,双向绑定原理,被虐的怀疑人生)!
-
尽量从面试官的问题中表现自己知识的深度与广度,让面试官发现你的闪光点!
-
多刷面经!
我把所有遇到的面试题都做了一个整理,并且阅读了很多大牛的博客之后写了解析,免费分享给大家,算是一个感恩回馈吧,有需要的朋友【点击我】免费获取。祝大家早日拿到自己心怡的工作!
篇幅有限,仅展示部分内容
来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
[外链图片转存中…(img-4Hgj3RrO-1713561406012)]
后记
总结一下这三次面试下来我的经验是:
-
一定不要死记硬背,要理解原理,否则面试官一深入就会露馅!
-
代码能力一定要注重,尤其是很多原理性的代码(之前两次让我写过Node中间件,Promise.all,双向绑定原理,被虐的怀疑人生)!
-
尽量从面试官的问题中表现自己知识的深度与广度,让面试官发现你的闪光点!
-
多刷面经!
我把所有遇到的面试题都做了一个整理,并且阅读了很多大牛的博客之后写了解析,免费分享给大家,算是一个感恩回馈吧,有需要的朋友【点击我】免费获取。祝大家早日拿到自己心怡的工作!
篇幅有限,仅展示部分内容