实际工作经验
无论是校招还是社招,企业都希望得到工作经验丰富的候选人。所以面试时会有很多面试题来考察候选人,是否有真实工作经验(而非只做过个人项目和 demo)。
为何考察?
企业都需要有工作经验的人才,入职之后简单培训就可以干活,不用再操心培养。毕竟现在人员流动很频繁。而且,有实际工作经验的,他之前踩过很多坑,未来工作就可以多一些稳定性。
各种能体现工作经验的题目,如
- 性能优化的实践
- 设计模式的应用
- 错误监控的实践 (不是真实项目,很少有错误监控)
看几个面试题:
- 如果一个网页访问慢,你该如何分析问题原因?
- Vue如何监听JS报错?
- 你遇到了哪些项目难点,如何解决的?
H5页面如何进行首屏优化
- 路由懒加载:适用于SPA,不适用于MPA。路由拆分,优先保证首页加载。
- 服务端渲染SSR:传统的前后端分离(SPA)渲染页面的过程复杂,SSR渲染页面过程简单,所以性能好。
- 如果是纯H5页面,SSR是性能优化的终极方案。
SSR是一门古老的技术,刚刚兴起Web1.0的时候,就是SSR技术,例如PHP、JSP、ASP等。后来出现了前后端分离,出现前后端分离后,大家就慢慢忘记了这种SSR技术,但是后来发现前端页面越来越大,越来越重,访问就比较慢了,大家又想起SSR技术了。但是由于前端已经用了Vue、React这种框架,如果再用PHP、JSP这些就不再兼容了,所以又重新造轮子,开发了Nuxt.js(Vue)和Next.js(React)。
如果H5是在App中展示的话,可使用App预取,例如用户访问列表页时,App预加载文章首屏内容,用户进入H5页,直接从App中获取内容,瞬间展示首屏。
针对列表页,可以采用分页的方式,默认只展示第一页的内容,上划加载更多。
图片懒加载Lazyload很常见,一般针对详情页,默认只展示文本内容,然后触发图片懒加载,注意的是:提前设置图片尺寸,尽量只重绘不重排。
如果是Hybrid的应用,提前将HTML、JS、CSS下载到App内部,在App webview中使用file://
协议加载页面文件,再用ajax获取内容并展示。
后端一次性返回10w条数据,你该如何渲染?
首先这个技术方案设计本身就是不合理的,没有后端一次性返回10w条数据,一般我们是分页返回,例如一共有10w条数据,我们每一页返回100个。返回10w个数据它的渲染和加载都是有问题的,遇到这种问题,主动和面试官沟通此事,这也许是面试官所期待的。如果面试官非要这么做,那再继续寻找解决方案。
处理10w条数据JS是没有问题,有问题的是渲染到DOM会非常卡顿,比如我们在网上写文章,几百行就会有些卡顿,所以说DOM是个瓶颈。那么怎么解决呢?
第一种方式,我们可以采用自定义nodejs中间层,获取并拆分这10w条数据,前端对接nodejs中间层,而不是服务端。这样成本比较高。
第二种方式,使用虚拟列表,只渲染可视区域DOM,其他隐藏区域不显示,只用<div>
撑起高度。随着浏览器滚动,随时创建和销毁DOM。虚拟列表实现起来非常复杂,在实际工作中,可借用第三方lib,比如vue的话可以使用Vue-virtual-scroll-list,react可以使用React-virtualiszed。
前端常用的设计模式有哪些?并说明使用场景
作为前端优秀程序员必须要了解前端常用的设计模式,例如:
- 工厂模式:用一个工厂函数,来创建实例,隐藏new,如jQuery $函数、React的createElement函数。
- 单例模式:全局唯一的实例(无法生成第二个),例如Vuex Redux的store,全局唯一的dialog modal。
- 代理模式:使用者不能直接访问对象,而是访问一个代理层,在代理层可以监听get set做很多事情,如ES6 Proxy实现Vue3响应式。
- 装饰器模式:原功能不变,增加一些新功能(AOP面向切面编程),ES和Typescript的Decorator语法。
观察者模式和发布订阅模式的区别
观察者模式一个主题绑定一个监听,直接触发事件就可以了,主题和监听是直接绑定,没有中间媒介,如addEventlistener绑定事件。发布订阅模式有一个Event Channel、Publisher和Subscriber,其中Publisher和Subscriber是不认识的,中间有一个Event Channel中间媒介隔离开,如EventBus自定义事件。
你在实际工作中,做过哪些Vue优化?
Vue优化在很多地方都有,不管是视频还是文章,而且是面试必考题,面试官有事没事就会问你Vue优化和React优化。
- v-if和v-show:v-if彻底销毁组件,v-show使用CSS隐藏组件,大部分情况下使用v-if更好,不要过度优化。
- v-for使用key:现在也不算优化项了,开发环境下不使用key会提示报错。
- 使用computed缓存:当你组件数据比较大,计算比较繁琐就可以缓存起来。
- keep-alive缓存组件:频繁切换的组件,如tabs,不要乱用,缓存太多会占用内存,不好debug。要在特定场景下使用。
- 异步组件:针对体积较大的组件,如编辑器、复杂表格、复杂表单等,通过拆包,需要时异步加载,不需要时不加载,较小主包的体积,首页会加载更快。
- 路由懒加载:项目比较大,拆分路由,保证首页先加载。
- 服务端渲染SSR:可使用Nuxt.js,按需优化,使用SSR的成本比较高。
性能优化要按需进行,不要为了优化而优化。面试是面试,工作是工作。工作中用不到,面试中也要答出来。
你使用Vue遇到过哪些坑?
- 内存泄露:因为组件绑定了全局变量、全局事件、全局定时器以及自定义事件没有销毁而造成内存泄露。
- Vue2响应式的缺陷(Vue3不再有):data新增属性用Vue.set,删除属性用Vue.delete,无法直接修改数据
arr[index]=value
- 路由切换时scroll到顶部:它是SPA的通病,不仅仅是Vue,如列表页,滚动到第二屏,点击进入详情页,再返回到列表页(此时组件重新渲染)就scroll到顶部。它的解决方案是在列表页缓存数据和scrollTop值,当再次返回列表页时,渲染组件,执行scrollTo(xx)。
工作中遇到哪些项目难点,如何解决的?
首先遇到问题要注意积累,如果平时没注意积累的话,现在积累一点也不晚。每个人都会遇到难题,总会有几个问题让你抓耳挠腮。日常要注意积累,解决了问题就自己写文章复盘一下。
如果之前没有积累的话,回顾一下半年之内你遇到的一个难题(肯定会有的),想一下当时的解决方案,以及解决之后的效果。写一篇文章记录一下。
回答的答案模板如下:
- 描述问题:背景+现象+造成的影响
- 问你如何被解决:分析+解决
- 自己的成长:学到了什么+以后如何避免
如何统一监听Vue组件报错
第一种方式通过window.onerror,try catch捕获的error,无法被window.onerror监听到。也可以使用window.addEventListener('error',callback)也可以。
第二种方式使用vue提供的错误监听声明周期,errorCaptured它可以监听所有下级组件的错误,返回false会阻止向上传播。
第三种方式使用errorHandler,它是Vue全局错误监听,所有组件错误都会汇总到这里,但errorCaptured返回false,不会传播到这里。
实际工作中以上三者结合使用。
如果H5很慢,你该如何排查性能问题
首先需要和面试官沟通一下是哪里慢,加载慢?访问慢?还是操作慢?这能能缩小题目范围,如果不能缩小,直接说客户说慢,让你去分析为什么会慢。面试官、公司或部门都需要招聘有积极主动沟通意识的程序员,遇到问题之后可以向反馈问题的人主动沟通,明确这个问题。
大家记得有问题的时候一定要把问题的现象告诉要提问的人,不能说有问题,而是报什么问题,有截图,详细的告诉提问人。
这个题可以把很慢作为一个范围,没有别的,那我们该怎么办?
首先我们排查问题的时候要知道性能指标,要知道根据什么样的标准去发现这样的问题,如果没有指标,仅通过猜测、推断,没有结论。所以前端的指标如下:
- First Paint(FP),第一次渲染
- First Contentful Paint(FCP),第一次有内容的渲染
- First Meaningful Paint(FMP)-已弃用,改用LCP,第一次有意义的渲染
- DomContentLoaded(DCL),Dom内容全部加载完成
- Largest Contentful Paint(LCP),最大内容的渲染
- Load(L)
chrome devtools的Performance可查看上述性能指标,并有网页快照。
lighthouse是非常流行的第三方评测工具,支持移动端和PC端,能够生成评测报告,包括优化建议。
如果是网页加载慢:
- 优化服务端硬件配置,使用CDN
- 路由懒加载,大组件异步加载,减少主包的体积。
- 优化HTTP缓存策略
如果是渲染慢
- 优化服务端接口(如Ajax获取数据慢)
- 继续分析,优化前端组件内部的逻辑(参考Vue、React的优化)
- 服务端渲染SSR
性能优化是一个循序渐进的过程,不像bug一次性解决,持续跟进统计结果,再逐步分析性能瓶颈,持续优化。可以使用第三方统计服务,如阿里云ARMS、百度统计等。
总结一下流程就是分析性能指标,找出慢的原因。对症下药,使用二分法,可逐步找到问题根源,解决问题。持续跟进,持续优化,要有监控的思维,解决了问题,还得保持住。
项目中有没有发生过沟通的冲突(和其他角色)?如何解决的
分析
有项目有合作,有合作就有沟通,有沟通就有冲突,这很正常。哪怕你自己单独做一个项目,你也需要和你的老板、客户沟通。面试官通过考察这个问题,就可以从侧面得知你是否有实际工作经验。
因为即便你是一个项目的“小兵”,不是负责人,你也会参与到一些沟通和冲突中,也能说出一些所见所闻。当然,如果你之前是项目负责人,有过很多沟通和解决冲突的经验,并在面试中充分表现出来。
相信面试官会惊喜万分(前提是技术过关),因为“技术 + 项目管理”这种复合型人才非常难得。
常见的冲突
- 需求变更:PM 或者老板提出了新的需求
- 时间延期:上游或者自己延期了
- 技术方案冲突:如感觉服务端给的接口格式不合理
正视冲突
从个人心理上,不要看到冲突就心烦,要拥抱变化,正视冲突。冲突是项目的一部分,就像 bug一样,心烦没用。
例如,PM 过来说要修改需求,你应该回答:“可以呀,你组织个会议讨论一下吧,拉上各位领导,因为有可能会影响工期。”
再例如,自己开发过程中发现可能会有延期,要及早的汇报给领导:“我的工期有风险,因为 xxx 原因,不过我会尽量保证按期完成。”
千万不要不好意思,等延期了被领导发现了,这就不好了。
解决冲突
合作引起的冲突,最终还是要通过沟通来解决。
一些不影响需求和工期的冲突,如技术方案问题,尽量私下沟通解决。实在解决不了再来领导开会。
需求变更和时间延期一定要开会解决,会议要有各个角色决定权的领导去参与。
注意,无论是私下沟通还是开会,涉及到自己工作内容变动的,一定要有结论。最常见的就是发邮件,一定要抄送给各位相关的负责人。这些事情要公开,有记录,不要自己偷偷的就改了。
如何规避冲突
- 预估工期留有余地
- 定期汇报个人工作进度,提前识别风险
答案
- 经常遇到哪些冲突
- 解决冲突
- 自己如何规避冲突
PS:最好再能准备一个案例或者故事,效果会非常好,因为人都喜欢听故事。
如果线上出现 bug,你该如何处理?
- 先回滚(而不是先排查问题),出现 bug 之后要先回滚,先回滚到之前的状态。
- 然后再去排查解决问题,测试、重新上线。
- 最后,组内复盘(大公司经常做的事情)。
从零搭建开发环境,需要考虑什么?
- 代码仓库,发布到哪个 npm 仓库
- 框架 Vue,React
- 代码目录规范
- 打包构建 Webpack等,做打包优化
- eslint、prettier、commit-lint
- pre-commit
- 单元测试
- CI/CD 流程
- 开发环境,预发布环境
- 开发文档
设计模式在前端开发中的应用场景?
- 观察者模式(DOM 事件)
- 发布订阅模式(自定义事件)
- 装饰器模式(Decorator)
- 代理模式(Proxy)
- 迭代器模式(Generator,for...of)