总结一下

面试前要精心做好准备,简历上写的知识点和原理都需要准备好,项目上多想想难点和亮点,这是面试时能和别人不一样的地方。

还有就是表现出自己的谦虚好学,以及对于未来持续进阶的规划,企业招人更偏爱稳定的人。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

  • 二、开始手操

    • 1. 先创建一个vue组件
  • 2. 实现基本的倒计时组件

  • 3. 为什么要**用setTimeout来模拟setInterval的行为**?

  • 4. 为什么要clearTimeout(this.timer)

  • 5. 使用 diffTime

  • 6. 添加新功能:可以传入到期时间。

  • 7. 添加新功能:可以选择要显示的内容,例如只显示秒,或者只显示小时。

  • 三、学习总结

一、前言


入职的第一个需求是跟着一位前端大佬一起完成的一个活动项目。

由于是一起开发,喜欢阅读源码的我,当然不会放过阅读大佬的代码的机会。

因为我的页面中需要使用到倒计时功能,发现大佬的已经写了个现成的倒计时组件,于是直接就拿过来用了。

传个参数就实现了功能的感觉真是太棒了。项目完成后,就膜拜了一下大佬的倒计时组件的代码。真是让我学到了不少。列举如下:

  1. 计时器为什么要用setTimeout而不用setInterval

  2. 为什么不直接将剩余时间-1。

  3. 如何将所需要的时间返回出去(有可能我只需要分钟和秒数,那就只返回分钟和秒数,也有可能我全都要)。

  4. 不确定接口返回的是剩余时间还是截止日期,该怎么同时兼容这两种情况。

  5. 不确定接口返回的时间是秒还是毫秒单位。

好了,你可能不太理解这些问题,但是没关系,看完下面的解释,相信你会豁然开朗。

二、开始手操


1. 先创建一个vue组件

2. 实现基本的倒计时组件

接下来,假设接口获得的是一个剩余时间。

将剩余时间time传入这个倒计时组件,由于time可能是秒为单位的,也有可能是毫秒为单位的,所以我们需要在传入time的是有也传入一个isMilliSecond来告诉倒计时组件这个time是毫秒还是秒为单位的。如下代码中的props所示。

computed中的duration是将time进行转化的结果,不管time是毫秒还是秒,都转化为秒 不知道你注意到了没有:+this.time。为什么要在前面加个‘+’号。这点很值得我们学习,因为接口返回的一串数字有时候是字符串的形式,有时候是数字的形式(不能过分相信后端同学,必须自己做好防范)。所以通过前面加个‘+’号 通通转化为数字。现在的duration就是转化后的time啦!

我们获得duration之后就可以开始倒计时了

在这里创建了一个countDown方法,表示开始倒计时的意思,已进入页面就开始执行countdown方法。

countDown方法调用了getTime方法,getTime需要传入duration这个参数,也就是我们获得的剩余时间。

现在来实现一下这个方法。

还剩{{day}}天{{hours}}:{{mins}}:{{seconds}}

可以看到,getTime的目的就是获得 days,hours,mins,seconds,然后显示到html上,并且通过定时器实时来刷新days,hours,mins,seconds这个几个值。从而实现了倒计时。很简单,有木有?

durationFormatter是一个将duration转化成天数,小时,分钟,秒数的方法,很简单,可以看下它的具体实现。

durationFormatter(time) {

if (!time) return { ss: 0 };

let t = time;

const ss = t % 60;

t = (t - ss) / 60;

if (t < 1) return { ss };

const mm = t % 60;

t = (t - mm) / 60;

if (t < 1) return { mm, ss };

const hh = t % 24;

t = (t - hh) / 24;

if (t < 1) return { hh, mm, ss };

const dd = t;

return { dd, hh, mm, ss };

},

好了,问题开始来了!!

3. 为什么要用setTimeout来模拟setInterval的行为?

这里用setInerval不是更方便吗?

setTimeout(function(){··· }, n); // n毫秒后执行function

setInterval(function(){··· }, n); // 每隔n毫秒执行一次function

可以看看setInterval有什么缺点:

再次强调,定时器指定的时间间隔,表示的是何时将定时器的代码添加到消息队列,而不是何时执行代码。所以真正何时执行代码的时间是不能保证的,取决于何时被主线程的事件循环取到,并执行。

setInterval(function, N)

//即:每隔N秒把function事件推到消息队列中

上图可见,setInterval每隔100ms往队列中添加一个事件;100ms后,添加T1定时器代码至队列中,主线程中还有任务在执行,所以等待,some event执行结束后执行T1定时器代码;又过了100ms,T2定时器被添加到队列中,主线程还在执行T1代码,所以等待;又过了100ms,理论上又要往队列里推一个定时器代码,但由于此时T2还在队列中,所以T3不会被添加,结果就是此时被跳过;这里我们可以看到,T1定时器执行结束后马上执行了T2代码,所以并没有达到定时器的效果。

综上所述,setInterval有两个缺点:

  1. 使用setInterval时,某些间隔会被跳过;

  2. 可能多个定时器会连续执行;

可以这么理解:每个setTimeout产生的任务会直接push到任务队列中;而setInterval在每次把任务push到任务队列前,都要进行一下判断(看上次的任务是否仍在队列中)。

因而我们一般用setTimeout模拟setInterval,来规避掉上面的缺点。

4. 为什么要clearTimeout(this.timer)

第二问:为什么要有this.timer && clearTimeout(this.timer);这一句?

假设一个场景:

如图所示,在倒计时的父组件中,有两个按钮,点击活动一就会传入活动一的剩余时间,点击活动二,就会传入活动二的时间。

如果此时倒计时组件正在做活动一的倒计时,然后点击活动二,就要会马上传入新的time,这个时候就需要重新计时。当然,这里并不会重新计时,因为组件的mounted只会执行一次。也就是说this.countDown();只会执行一次,也就是说this.getTime(this.duration);只会执行一次,因此duration还是活动一的时间,怎么办呢?watch派上用场了。

我们来监听duration,如果发现duration变化,说明新的时间time传入组件,这时就要重新调用this.countDown()。

代码如下:

还剩{{day}}天{{hours}}:{{mins}}:{{seconds}}

好了,但是并没有解释上面提出的那个问题:为什么要有this.timer && clearTimeout(this.timer);这一句?

这样,假设现在页面显示的是活动一的时间,这时,执行到setTimeout,在一秒后就会把setTimeout里的回调函数放到任务队列中,注意是一秒后哦!这时,然而,在这一秒的开头,我们点击了活动二按钮,这时候的活动二的时间就会传入倒计时组件中,然后触发countDown(),也就调用this.getTime(this.duration);,然后执行到setTimeout,也会一秒后把回调函数放到任务队列中。

这时,任务队列中就会有两个setTimeout的回调函数了。等待一秒过去,两个回调函数相继执行,我们就会看到页面上的时间一下子背减了2,实际上是很快速地进行了两遍减1的操作。

这就是为什么要添加上this.timer && clearTimeout(this.timer);这一句的原因了。就是要把上一个setTimeout清除掉。

5. 使用 diffTime

当你认为这是一个完美的组件的时候,你想把这个组件用到项目上,假设你也确实用了,而且还上线了,确发现出现了个大问题:当页面打开的时候,倒计时开始了,时间是 还剩1天12:25:25,然后有人给你发微信,你马上切换到微信,回复消息后切回浏览器,发现倒计时时间却还是还剩1天12:25:25。你慌了:你写的代码出现bug了!

这是怎么回事?

出于节能的考虑, 部分浏览器在进入后台时(或者失去焦点时), 会将 setTimeout 等定时任务暂停 待用户回到浏览器时, 才会重新激活定时任务

说是暂停, 其实应该说是延迟, 1s 的任务延迟到 2s, 2s 的延迟到 5s, 实际情况因浏览器而异。

原来如此,看来不能每次都只是减1这么简单了(毕竟你把浏览器切到后台之后setTimeout就冷却了,等几秒后切回,然后执行setTimeout,只是减了一秒而已)。

所以我们需要改写一下getTime方法。

还剩{{day}}天{{hours}}:{{mins}}:{{seconds}}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐