先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Web前端全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024c (备注前端)
正文
$(el).css({
‘top’:0,
‘left’:index*(box.width()/row)+‘px’
})
}
//第3,第4个方块,离右侧的距离是0,离顶部是逐一多一个方块的距离
//
else if(index>=row-1 && index<row+column-1){
$(el).css({
‘right’:0,
‘top’:(index-2)*(box.height()/column)+‘px’
})
}
//第5,第6个方法,离底部的距离是0,离右侧的距离逐一多一个方块的距离
else if(index>=row-1+column&&index<(2*row+column-2)){
$(el).css({
‘bottom’:0,
‘right’:(index-(row+column-2))*(box.width()/row)+‘px’
})
}
//第7,第8个,离左侧的距离是0,距离顶部的距离是处于第二排,第三排
else{
$(el).css({
‘top’:(index-(2*(row+column)-6))*(box.height()/column)+‘px’,
‘left’:0
})
}
})
//创建开始按钮
let startBtn = <span id='${puginID+'StartBtn'}' class='start-btn start-btn-able'>开始</span>
;
//将按钮加入DOM
box.parent().append(startBtn);
给按钮设置样式,将其置于正中间
$(‘#’+puginID+‘StartBtn’).css({
‘width’:box.width()/row-4+‘px’,
‘height’:box.height()/column-4+‘px’,
‘line-height’:box.height()/column-4+‘px’,
‘left’:box.width()/row+‘px’,
‘top’:box.height()/column+‘px’,
// ‘transform’:‘translate(-50%,-50%)’
})
//返回按钮
return {
startBtn:puginID+‘StartBtn’,
boxId:puginID+‘Box’
}
}
筛选奖品和启动转动动画
在这个阶段,需要给开始按钮绑定点击事件,点击后可以启动转动动画,当然在启动之前,必须对奖品数组进行一系列检测,如果有错误进行简单的处理,最终返回一个我们需要的抽奖数组,这个最终的抽奖数组才上面插入DOM的div,也就是说,实际上对传入的参数进行检测这一步应该放在排列位置之前;
有了最终的合法的抽奖数组,那么就可以根据需求,筛选最终奖品;
检测参数
$.fn[plugin] = function(params) {
let _this = this;
if(!isObj(params)) throwError(‘传入的参数必须是一个对象’);
//再创建之前,需要先对传入的参数做一次检测,如果参数错误,长度错误可以及时补齐或抛出异常
params.prizeList = finalList(params.prizeList);
//此时的createDOMList仅仅是一个数组,尚未插入DOM树中
let createDOMList = createDomListArr(params.prizeList);
let btn = createDOM(createDOMList,_this);
}
//检测参数
function finalList(arr){
//存在且必须是数组
if(!(arr && Array.isArray(arr))){
let newArr = [];
for(let i = 0 ; i < maxListNumber ; i++){
//数组每一项都有名字,id和概率
newArr.push({
name:defaultName,
id:puginID + i,
percent:100 / maxListNumber
});
}
//返回数组
return newArr;
}
//概率这一项必须是数字
arr.forEach((el)=>{
if(!isNumber(el.percent)){
throwError(‘奖品列表的percent的值必须是数字类型,当前ID为:’+el.id+’ 的percent值不是数字’);
}
})
//奖品列表长度必须是8
if(arr.length === maxListNumber){
//概率的总和必须是100,不能8个方块的概率加起来超出100了
let percent = resultPro(arr);
if(percent !== 100) throwError(‘奖品列表的概率和必须是100,当前是:’+percent);
return arr;
}
else{
//假如传入的参数的长度超过了8,提示
let length = maxListNumber - arr.length;
length = length > 0 ? length : throwError(‘奖品列表的数量上限是:’+maxListNumber+‘,当前是:’+arr.length);
//当前概率和
let current = resultPro(arr);
if(current>100) throwError(‘奖品列表的概率和必须小于100,当前是:’+current);
for(let i = 0 ; i < length ; i++){
arr.push({
name:defaultName,
id:puginID + i,
percent:(100 - current) / length
})
}
//返回打乱的数组,不能是输入的奖品顺序是什么就是什么
return arr.sort(randomArr);
}
}
//判断当前的奖品列表的概率总计
function resultPro(arr){
if(!Array.isArray(arr)) throwError(‘resultPro的参数必须是数组’);
let result = 0;
arr.forEach((el) => {
el.percent && isNumber(el.percent)? result = result + el.percent : ‘’;
})
return result;
}
//打乱数组
function randomArr(a,b){
return Math.random()>.5 ? -1 : 1;
}
//抛出异常
function throwError(val){
throw new Error(val)
}
等检测完,此时返回的抽奖数组就是一个完整的奖品数组了,在第一步创建div的时候就可以按照这个顺序直接创建div并排列;
点击开始按钮
到这一阶段,就需要给开始按钮添加点击事件了,并且点击后开始按钮进入disable的状态,不然连续点击就会出现问题,并且,点击“开始”按钮后,会出现两种情况:
-
存在指定奖品,也就是俗称的黑幕,不管谁抽,都是谢谢惠顾之类的;
-
不存在指定奖品,那么就会按照设定的概率进行抽奖;
$.fn[plugin] = function(params) {
let _this = this;
if(!isObj(params)) throwError(‘传入的参数必须是一个对象’);
//生成抽奖数组
params.prizeList = finalList(params.prizeList);
let createDOMList = createDomListArr(params.prizeList);
//创建DOM并返回按钮ID
let btn = createDOM(createDOMList,_this);
let boxChinldren = btn.boxId;
$(‘#’+btn.startBtn).on(‘click’,function(){
this = this;
//通过flg开关,判断是否可以点击
if(!flg){
//添加不可点击时的样式;
$(this).addClass(‘start-btn-disable’).removeClass(‘start-btn-able’);
flg = true;
//判断是否有指定奖品ID
//假如有指定奖品,那么概率抽奖就不会生效,假如没有,那么就进行概率抽奖
if(params.finalPrizeID&&isString(params.finalPrizeID)){
//判断一下设定的最终奖品id存不存在
//不要设定了一个奖品id,结果奖品列表中没有,或者有2个及2个以上的奖品
let array = [];
params.prizeList.forEach(element => {
if(element.id === params.finalPrizeID){
array.push(element);
}
})
//根据数组长度进行判断
switch(array.length){
//长度是0,那么就说明指定的id不存在,那么将进行概率抽奖
case 0:
console.log(‘指定的奖品ID在奖品列表中不存在,将按指定概率进行抽奖’);
//这个是抽奖函数,下一大节解释这个函数
targetPrize(params.prizeList,boxChinldren);
break
//长度是1,那么这个就是正常情况,这个奖品就是最终奖品
case 1:
let name = array[0].name?array[0].name:‘默认名字’;
console.log(‘指定奖品为:’+name);
targetPrize(array[0],boxChinldren);
break
//长度超出了1个,那么就是存在多个相同id的最终奖品,其实也可以进行概率抽奖
default:
throwError(‘指定的最终奖品ID在奖品列表中不唯一’);
break;
}
}
//没有指定奖品,那么就正常进行概率抽奖
else{
console.log(‘无指定奖品,将按指定概率进行抽奖’);
targetPrize(params.prizeList,boxChinldren);
}
}
})
}
抽奖函数
在上一大节中,通过targetPrize函数,进行抽奖,其中第一个参数:
-
如果是一个对象,那么就代表直接传递过来了最终奖品,那么就不需要通过函数去计算哪个是最终奖品;
-
如果是一个数组,那么代表使用者并没有设定最终奖品,需要按照概率进行随机抽取;
其中,如果是数组,大致上就是将数组中的每一项奖品的概率转成一个区间,比如:第一个奖品的概率是10,那么在100中,随机数0-9指的就是这个奖品,如果第二个奖品的该也是10,那么转换后10-19就是这个奖品,第三个奖品的概率是30,那么它所对应的区间就是20-59,以此类推;
这样就将奖品的概率平铺满了100,到这里的抽奖只需要随机数一个0-100的数字,这个数字在哪个区间,就代表抽中了哪个奖品;
//执行抽奖,传入的正常抽奖或者是指定奖品,dom列表
function targetPrize(params,dom){
//如果是对象,执行指定奖品,如果是数组,执行概率抽奖
isObj(params)?
pointPrize(params,dom):
Array.isArray(params)?
percentPrize(params,dom):
throwError(‘targetPrize()参数错误’);
}
//指定奖品
function pointPrize(params,dom){
//指定产品的位置
let ax = targetIndex(params,dom)
console.log(params);
speedUp(dom,ax);
}
//概率抽奖
function percentPrize(params,dom){
//将概率转成数组区间
let newArr = arrayPercent(params);
//获得最终奖品
let percent = objPercent(newArr);
console.log(percent);
//指定产品的位置
let ax = targetIndex(percent,dom)
speedUp(dom,ax);
}
//将概率转成区间数组
function arrayPercent(arr){
let sum = 0;
let newArr=[];
arr.forEach((el)=>{
el.percent&&isNumber(el.percent)?
newArr.push({
name:el.name,
id:el.id,
percent:[sum,(sum+el.percent)===100?(sum=sum+el.percent):(sum=sum+el.percent)-1]
}):‘’;
})
return newArr;
}
//选出一个随机数并返回指定区间的对象
function objPercent(arr){
let radomNum = Math.floor(Math.random() * 100);
console.log(radomNum);
for(let el of arr){
if(radomNum >= el.percent[0] && radomNum <= el.percent[1]){
return el;
}
}
}
转动动画
转动动画是通过div的背景色的顺时针的顺序切换实现的,通过不断的顺时间变化给人一种转动的感觉,而启动动画就是开始每一个变化的间隔都较长,然后变化的间隔逐渐变短,造成加速的视觉过程;减速同理,也就是间隔变长导致了转速下降的视觉错觉;
这是一个选中div的函数,因为不管是加速,匀速,减速,都是需要选中div改变背景色,因此这个过程抽离了出来,方便在三个速度中调用
//选中dom对象
function runAnimate(dom){
if(i<7){
i++;
}
else{
i=0;
}
$(‘#’+dom).children().removeClass(‘selected’).eq(i).addClass(‘selected’);
}
加速动画
//不管是概率抽奖还是指定奖品抽奖,最终都会执行到这个加速动画
//设定时间
const normalTime = 50,maxTime=300;
//转动次数
const normal = 2400/normalTime;
let timer,i,t;
let v;
const a=-20;
//执行动画,加速
function speedUp(dom,index){
//将dom传递进去,当然也可以直接将dom写进选中的函数里
runAnimate(dom);
//如果间隔已经达到设定的值,那么就执行匀速动画函数
if(v<=normalTime){
v=normalTime;
clearTimeout(timer);
speedNormal(dom,index);
}
//else里面则是间隔还没有达到设定的要求,还需要继续循环加速
else{
v = v+a;
timer = setTimeout(()=>{
speedUp(dom,index)
}, v);
}
}
总结
大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
e;
clearTimeout(timer);
speedNormal(dom,index);
}
//else里面则是间隔还没有达到设定的要求,还需要继续循环加速
else{
v = v+a;
timer = setTimeout(()=>{
speedUp(dom,index)
}, v);
}
}
总结
大厂面试问深度,小厂面试问广度,如果有同学想进大厂深造一定要有一个方向精通的惊艳到面试官,还要平时遇到问题后思考一下问题的本质,找方法解决是一个方面,看到问题本质是另一个方面。还有大家一定要有目标,我在很久之前就想着以后一定要去大厂,然后默默努力,每天看一些大佬们的文章,总是觉得只有再学深入一点才有机会,所以才有恒心一直学下去。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-1XTELYTO-1713206667530)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!