前言
都知道前端面试中,面试官最爱拷打的项目细节,根据你的项目经历来进行相关提问,时不时再给你几个高难度问题,让人头疼。
程序员大都有一个特点:会做,不会写,更不会说
前端面试,以及任何技术岗位的面试,都离不开项目这个环节,这是必考。简历中要写项目,面试时要聊项目。
基础知识、八股文、原理源码等这些,都是可以通过学习甚至背诵来补齐的。但项目不行,你再努力也弥补不了自己的真实项目经历。有经验的面试官,会通过项目问题来考察候选人的真实技术能力。
本文梳理了一整套面试官经常拷打的问题,针对项目来说都有不错的回答!
另外还会附一些最近比较火爆的场景题,还有一些八股之类的!
感觉有帮助可以【点击此处】
那么展示一波开始正文:
前端资料
正文
2024年前端项⽬细节及疑难点
1. 测试和调试
H5 ⻚⾯需要在多种设备和环境下进⾏测试,确保其稳定性和兼容性。
解决方法:
• 使用模拟器或真实设备进行测试。
• 利⽤浏览器的开发者⼯具进⾏调试。
• 采用自动化测试框架,如 Selenium 或 Appium ,进行持续集成和测试。
通过了解和解决这些常见的问题,开发者可以提⾼ H5 ⻚⾯的质量和性能,为⽤⼾提供更好的体验。
⽽持续学习和适应新技术才是避免和解决这些问题的关键
2. 跨域请求问题
在进⾏ Ajax 请求或 API 调⽤时,可能会遇到跨域问题,导致请求失败。
解决⽅法:
• 使⽤ JSONP 来绕过同源策略限制。
• 在服务器端设置 CORS(跨源资源共享)策略,允许特定的外部域访问资源。
3. 数据安全和隐私保护
在处理⽤⼾数据时,开发者必须确保数据的安全性和⽤⼾的隐私权。
解决⽅法:
• 采⽤ HTTPS 协议来加密数据传输。
• 遵循数据最⼩化原则,只收集必要的⽤⼾信息。
• 提供清晰的隐私政策,告知⽤⼾数据的使⽤⽅式和⽬的
4. 移动端触摸事件处理
在移动端,触摸事件的处理与桌⾯端的⿏标事件有所不同,需要特别注意。
解决⽅法:
• 使⽤触摸事件(touchstart, touchmove, touchend)代替⿏标事件。
• 考虑使⽤框架或库,如 jQuery
5. 性能优化
H5 ⻚⾯的性能直接影响⽤⼾体验。加载时间过⻓或运⾏缓慢的⻚⾯会导致⽤⼾流失。
解决⽅法:
• 对图⽚和视频进⾏压缩,减少资源⽂件的⼤⼩。
• 利⽤浏览器缓存和 CDN 服务来加速资源的加载。
• 优化 CSS 和 JavaScript 代码,避免重绘和重排,提⾼⻚⾯渲染效率。
6. 响应式布局的挑战
为了适应不同屏幕尺⼨和分辨率,开发者需要创建响应式布局。这可能导致 CSS 和 JavaScript 代码复杂,难以维护。
解决⽅法:
• 使⽤媒体查询来适应不同的屏幕尺⼨。
• 利⽤CSS框架,如 Bootstrap 或 Foundation ,它们提供了⼀套响应式⽹格系统,简化了布局的开发。
7. 浏览器兼容性问题
在开发 H5 ⻚⾯时,开发者需要考虑到不同浏览器和设备的兼容性。⼀些特性在某些浏览器上可能不被⽀持,或者在不同浏览器上表现不⼀致。
解决⽅法:
• 使⽤特性检测库,如 Modernizr ,来检测浏览器是否⽀持特定的功能。
• 采⽤渐进增强的策略,确保基础功能在所有浏览器上都能正常⼯作,⾼级功能则根据浏览器能⼒逐步增强
8. 获取⾸⻚链接⾥⾯的参数问题。
获取是可以获取到,只要不跳转出这个项⽬的⻚⾯,都是可以的,但是该项⽬链接了许多外链,所以,有时候返回的时候,⻚⾯就会显⽰空⽩,因为获取的参数出了问题。解决办法:将参数设置成了缓存,但是返回的速度快了,⾸⻚同样还是会出现拿不到参数,的问题。
解决⽅法:将获取连接的templateId写在Home⻚⾯1 if (templateId) {
1 if (templateId) {
2 this.$store.commit('updateTemplatedId',templateId);
3 window.localStorage.setItem('templateId', templateId);
4 console.log('store===templateId',this.$store.state.templateId)
5 }else{
6 setTimeout(function() {
7 window.location.reload()
8 }, 1500);
9 }
10
9. 更新⽂件缓存的坑。
每次打包好⽂件给后端更新的时候,⽤⼾⼿机上总会留下,上次版本的信息,⽽且每次都得清下缓存,才会显⽰最新版本的数据。后来,我师傅提了个建议,让后端返回⼀个更新版本的接⼝,前端每次更新版本的时候,都会给后端传⼊时间戳,然后后端接收后判断和库⾥的时间戳是否相同,相同的返回不需要更新,不相同的话,返回要更新,然后前端这边的处理⽅法是:需要更新的话,清除掉缓存,刷新⻚⾯即可。
虽然说给.js .css⽂件后缀加上时间戳也是可以的,但是⻚⾯的⼊⼝index.html每次都是⼀样的,所以。。。就不会更新,,百度⼀些说在nginx服务器上,写上强制更新,但是由于公司服务器上的⽂件很多,万⼀操作失误那就⿇烦了
10. 解析后端返回的map格式数据的坑。
之前解析数据的时候,直接就可以拿去,然后直接渲染⻚⾯使⽤即可。但是这次遇到后端返回的是map格式的数据,这就得解析下了。 例如:body['1'] 。根据返回的格式,⾃⼰解析成⾃⼰需要的数据格式。
11. vue组件动态加载的坑。
由于⾸⻚的排版不确定,然后想着,让组件动态显⽰,根据后端传⼊的数据,传⼊那个组件的数据,就显⽰那个组件。解决办法:和后端商量好,做个标识。前端根据标识判断,动态显⽰组件。 使⽤到了vue中的 , 刚开始想着是不是和原⽣js⼀样使⽤append直接可以插⼊进⼊呢,但是后来发现根本不可以,思路是可以的,但是实现起来是⾏不通的。因为append后⾯插⼊的必须是个节点,⽽不是组件。后来就去查阅vue⽂档。
12. ⻚⾯缓存的坑。
有个填写信息的⻚⾯,需要填写⼀部分信息,进⼊查新协议⻚⾯,返回的时候,⻚⾯上填写的信息还需要留存。 解决办法:使⽤vue提供的keep-alive,来完成⻚⾯的缓存的。
13. 路由传参的功能的坑。
之前⼀直使⽤路由传参,但是当本⻚⾯刷新的时候,⻚⾯上是没有参数的,因为参数是从上个⻚⾯传⼊进来的。 解决办法:使⽤了缓存,和vuex状态管理。但是由于项⽬并不是很⼤型的项⽬,所以使⽤最多的是缓存。
14. axios请求中post请求的坑。
刚开始的坑是,使⽤axios的post⽅法请求数据,数据被拦截,数据⼀直传不到后端那边。后来查⽂档才得知 axios对于post请求是有拦截功能的,需要⾃⼰判断,或者使⽤提请的 qs ⽅法,将传给后端的数据进⾏下处理。
15. 为什么需要⼆次封装组件库?
实际⼯作中,我们在项⽬中需要⾃定义 主题⾊ , 更改按钮样式 , ⾃定义图标 ,⾃定义 table组件 等等,这些都可以基于antd组件库进⾏⼆次封装,减少重复⼯作,提升开发效率。
所以我们在封装的时候按照下⾯这四个原则进⾏思考就⾏了,另外本⾝封装组件库对于项⽬来说也是没有任何⻛险,因为⼀开始我们把 PropsType 直接进⾏ 转发 ,内部再进⾏增加业务的功能,这样就是达到完全的 解耦
• 统⼀⻛格:在⼀个⼤的项⽬或者多个相关的项⽬中,保持⼀致的界⾯⻛格和交互⽅式是⾮常重要的。通过⼆次封装,我们可以定义统⼀的样式和⾏为,减少不⼀致性。
• 降低维护成本:当底层的组件库更新时,我们可能需要在项⽬的多个地⽅进⾏修改。但是如果我们有了⾃⼰的封装,只需要在封装层⾯进⾏更新即可,这⼤⼤降低了维护成本。
• 增加定制功能:有些时候,我们需要在原有组件库的基础上增加⼀些特定的功能,如特定的验证、错误处理等。⼆次封装提供了这样的可能。
• 提⾼开发效率:在⼀些常⽤的功能(如表单验证、全局提⽰等)上,⼆次封装可以提供更⽅便的API,提⾼开发效率。
16. 请结合⼀个组件库设计的过程,谈谈前端⼯程化的思想当我们结合⼀个组件库设计的过程来谈论前端⼯程化的思想时,需要理清这些要点:
1. 使⽤ Lerna 进⾏多包管理:通过 Lerna 来管理多个包(组件),实现组件级别的解耦、独⽴版本控制、按需加载等特性。
1 # 安装 Lerna
2 npm install -g lerna
3
4 # 初始化⼀个 Lerna 仓库
5 lerna init
6
7 # 创建 "Button" 组件包
8 lerna create button --yes
2. 规范化提交:使⽤规范化的提交信息可以提⾼ Git ⽇志的可读性,并且可以通过 conventionalcommits ⾃动⽣成 CHANGELOG。可以使⽤ commitizen、commitlint 等⼯具来配
置。
1 # 安装相关⼯具
2 npm install commitizen cz-conventional-changelog --save-dev
1 // package.json
2 {
3 "scripts": {
4 "commit": "git-cz"
5 },
6 "config": {
7 "commitizen": {
8 "path": "cz-conventional-changelog"
9 }
10 }
11 }
12
3. 代码规范化:通过 ESLint、Prettier 等⼯具实现代码规范化和格式化,并封装为⾃⼰的规范预设。
4. 组件开发调试:需要考虑热更新编译、软链接引⽤等问题,以⽅便在开发过程中进⾏组件的调试。
5. ⽂档站点:可以基于 dumi 搭建⽂档站点,并实现 CDN 加速、增量发布等优化。可以使⽤ surge实现 PR 预览。
6. 单元测试:需要考虑 jest、enzyme 等⼯具的配合使⽤,⽣成测试覆盖率报告。7. 按需加载:需要配合 babel-plugin-import 实现按需加载,即在编译时修改导⼊路径来实现组件的按需加载。
8. 组件设计:需要考虑响应式、主题、国际化、TypeScript ⽀持等问题,以保证组件的灵活性和可扩展性。
9. 发布前的⾃动化脚本:需要编写⾃动化脚本来规范发布流程,确保发布的⼀致性和可靠性。
10. 发布后的处理:考虑补丁升级、⽂档站点同步发布等问题,以便及时修复问题并提供最新的⽂档。
11. 制定 Contributing ⽂档:制定 Contributing ⽂档可以降低开源社区贡献的⻔槛,并确保社区成员了解如何参与项⽬。处理 issues 和 PR 需要有专⼈负责。
17. 如何对⼀个组件库进⾏测试?
⾸先需要明确,组件库的测试⼤致可以分为两类:⼀类是针对组件本⾝的功能和性能的测试(例如,单元测试、性能测试),另⼀类是针对组件在集成环境下的⾏为和性能的测试(例如,集成测试、系统测试)。
1. 功能测试(单元测试)
通常来说,组件的功能测试可以通过单元测试来完成。单元测试的⽬的是验证组件的单个功能是否按照预期⼯作。这通常可以通过编写测试⽤例来完成,每个测试⽤例针对⼀个特定的功能。
2. 边界测试
边界测试是⼀种特殊的功能测试,⽤于检查组件在输⼊或输出达到极限或边界条件时的⾏为。
3. 响应测试
响应测试通常涉及到 UI 组件在不同的设备或屏幕尺⼨下的⾏为。这可能需要使⽤端到端(E2E)测试⼯具,如 Puppeteer、Cypress 等。
4. 交互测试
交互测试也可以通过端到端(E2E)测试⼯具来完成。
5. 异常测试
异常测试⽤于验证组件在遇到错误或⾮法输⼊时能否正确处理。这通常可以通过在测试⽤例中模拟错
误条件来完成。
6. 性能测试
性能测试⽤于验证组件的性能,例如,加载速度、内存消耗等。
7. ⾃动化测试
单元测试、集成测试和系统测试都可以通过⾃动化测试⼯具进⾏。例如,Jest 和 Mocha 可以⽤于⾃动化运⾏ JavaScript 单元测试,Puppeteer 和 Selenium 可以⽤于⾃动化运⾏端到端测试。
18. 在使⽤ qiankun 时,你如何处理多个⼦项⽬的调试问题?
在使⽤ qiankun 处理多个⼦项⽬的调试问题时,通常的⽅式是将每个⼦项⽬作为⼀个独⽴的应⽤进⾏开发和调试。每个⼦项⽬都可以在本地启动,并通过修改主应⽤的配置,让主应⽤去加载本地正在运⾏的⼦应⽤,这样就可以对⼦应⽤进⾏调试了。这种⽅式的好处是,⼦应⽤与主应⽤解耦,可以独⽴进⾏开发和调试,不会相互影响。
对于如何同时启动多个⼦应⽤,你可以使⽤ npm-run-all 这个⼯具。 npm-run-all 是⼀个CLI⼯具,可以并⾏或者串⾏执⾏多个npm脚本。这个⼯具对于同时启动多个⼦应⽤⾮常有⽤。
19. 你能解释⼀下 qiankun 如何实现 keep-alive 的需求吗?
在 qiankun 中,实现 keep-alive 的需求有⼀定的挑战性。这是因为 qiankun 的设计理念是在⼦应⽤卸载时,将环境还原到⼦应⽤加载前的状态,以防⽌⼦应⽤对全局环境造成污染。这种设计理念与 keep-alive 的需求是相悖的,因为 keep-alive 需要保留⼦应⽤的状态,⽽不是在⼦应⽤卸载时将其状态清除。
然⽽,我们可以通过⼀些技巧来实现 keep-alive 的效果。⼀种可能的⽅法是在⼦应⽤的⽣命周期函数中保存和恢复⼦应⽤的状态。
20. 在使⽤ qiankun 时,你如何处理 js 沙箱不能解决的js 污染问题?
qiankun 的 js 沙箱机制主要是通过代理 window 对象来实现的,它可以有效地隔离⼦应⽤的全局变量,防⽌⼦应⽤之间的全局变量污染。然⽽,这种机制并不能解决所有的 js 污染问题。例如,如果我们使⽤ onclick 或 addEventListener 给 <body> 添加了⼀个点击事件, js沙箱并不能消除它的影响。
对于这种情况,我们需要依赖于良好的代码规范和开发者的⾃觉。在开发⼦应⽤时,我们需要避免直接操作全局对象,如 window 和 document 。如果必须要操作,我们应该在⼦应⽤卸载时,清理掉这些全局事件和全局变量,以防⽌对其他⼦应⽤或主应⽤造成影响。
21. 在项⽬中有没有单独封装组件答:有的,在項⽬的 commen ⽂件下会存放项⽬公⽤组件(如:⻚⾯的头组件、⻚⾯底部组件等)项⽬⾥的feature ⽂件下则是放项⽬的功能组件(如:轮播图、分⻚器、上拉加载这些功能组件)把这些⻚⾯重复的部分,抽离出来进⾏单独的封装,有效的减少了代码量,提升了项⽬的开发效率。解决了传统项⽬中效率低、难维护、复⽤性低的等问题。
22. 在项⽬中发送请求怎么携带token
答:当⽤⼾登陆的时候,后端会把⽤⼾的信息和token返回给我们的,我们进⾏存储token,把存储的token,放在请求拦截器中,这样所有的请求都可以直接通过请求拦截器将token传给服务器。
23. ⼯作中有⽤到git吗
答:有的,在之前的公司⾥,基本上⽤的都是git进⾏多⼈开发,git是⼀个分布式版本管理⼯具,⾸⻚是获取项⽬:访问远程仓库复制项⽬链接,下载项⽬到本地。使⽤ git init ⽅法在项⽬根⽬录下,创建本地 git 仓库,进⾏⼀个开发,开发完毕后使⽤git add.⽅法将⽂件都加载到暂存区,再使⽤ gitcommit -m 提交代码到本地仓库,先pull远程仓库的代码(避免远程仓库与本地代码不⼀致时发⽣冲突),最后push 本地仓库的代码提交到远程仓库。还可以使⽤ git merge 将⼦分⽀代码合并到主分⽀代码仓库⾥。
24. git 版本发⽣冲突你怎么解决的
版本冲突基本出现在合并操作(合并远程仓库代码或者合并分⽀代码)中。如果出现版本冲突,需要具体分析出现冲突的代码区,⼿动进⾏代码合并,然后再进⾏提交。
25. 如何快速让⼀个盒⼦⽔平垂直居中
纯flex布局实现::给元素设置flex布局,添加flex的alignltems:center垂直居中,justifycontent:center⽔平居中,实现居中效果;
flex布局+外边距(margin)实现:给⽗级设置为display: flex;布局,/给⼦级添加 margin:auto;
就可以实现⽔平垂直居中显⽰;
绝对定位+外边距(margin)实现::绝对定位的元素将上下左右都设置为O,再设置margin:auto 即可实现居中;
绝对定位+外边距(margin)+C3的转换transform 中的translate实现::绝对定位元素,利⽤margin 偏移外容器的50%,再利⽤translate 回补⾃⾝宽⾼的50%;
26. ⾸屏加载⽩屏怎么进⾏优化
答:
(1)使⽤CDN 减⼩代码体积,加快请求速度;(2)SSR通过服务端把所有数据全部渲染完成再返回给客⼾端;
(3) 路由懒加载,当⽤⼾访问的时候,再加载相应模块;
(4) 使⽤外链CSS,JS⽂件;
(5) 开启 GZIP压缩;(是⼀种 http 请求优化⽅式,通过减少⽂件体积来提⾼加载速度。
html、js、css ⽂件甚⾄json数据都可以⽤它压缩,可以减⼩60%以上的体积。(需要后端⽀持))
(6) 项⽬打包不⽣成.map ⽂件;
(7)使⽤⻣架屏 在⾸⻚加载时,显⽰⻚⾯结构轮廓;
27. 路由传参 query与 params区别
答:query类似 get,跳转之后在地址栏中显⽰拼接参数,类似?id=1;params类似 post,跳转之后不在 url 中显⽰参数;相对于query⽐较安全;
注意点:(params 在进⾏路由传参时,要在路由中配置占位。如果不在路由中配置占位,跳转过去以后刷新⻚⾯会数据丢失,query参数数据不会丢失);
28. 项⽬基础优化
(1)減少 HTTP 请求数(避免重复请求)
(2)減少 DOM元素和 DOM 操作
(3)使⽤雪碧图
(4)压缩合井 JS、CSS代码
(5)避免图⽚ src为空
(6)把样式表放在 link 中
(7)css样式放置在⽂件头部
(8)js脚本放置在⽂件末尾
29. 对 $nextTick异步渲染的理解
答:Vue 采⽤了数据驱动视图的思想,但是在⼀些情况下,仍然需要操作DOM。有时候,DOM1的数据发⽣了变化,⽽DOM2需要从DOM1中获取数据,那这时就会发现DOM2的视图并没有更新,这时就需要⽤到了nextTick了;
作⽤:在下⼀次 DOM更新结束后执⾏其指定的回调;(当数据更新后,要基于更新后的新DOM进⾏某些操作时,要在nextTick指定的回调函数中执⾏)。如果不采⽤异步更新,在每次数据的更新后,都会对当前组件进⾏重新渲染。所以为了性能考虑,vue 会在本轮数据更新后,再去异步更新视图;
30. 你是怎么对axios进⾏⼆次封装的,有什么作⽤
答:
1.添加请求拦截器
在请求发送前进⾏必要操作处理,例如添加tokan、cookie 请求体加验证、设置请求头等,相当于是对每个接⼝⾥相同操作的⼀个封装;
2.添加响应拦截器
同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的⼀些处理,通常是数据统⼀处理等,也常来判断登录失效等。
31. ⽤⼾token 失效你是怎么处理的
答:当⽤⼾登陆的时候,接⼝的响应信息中是有三个和token相关的信息的,1.当前使⽤的token,⽤于访问需要授权的接⼝ 2.字段就是token的过期时间3.刷新获取新的token字段;
⽅式⼀:在请求拦截器,根据接⼝响应的过期时间判断token是否过期,如果过期则会刷新后再继续请求接⼝;缺点:1.后端需要提供Token过期时间字段,2.需要过期时间与本地时间进⾏判断,如果计算机时间被篡改时,拦截就会失败的;
⽅式⼆:在每次请求数据的时候都会携带
token,正常情况下接⼝返回的状态码是200,我们会在响应拦截器中,⾛成功的回调把接⼝中data数据进⾏返回,如果tokan失效后端会返回401的状态码,就表⽰没有tokan/tokam⽆效或者过期;
具体处理步骤:在响应拦截器的失败回调中,if判断 error.response状态码,等于401就代表着token⽆效/过期,那么我们会if判断 vuex的sdata.user 信息,如果说没有就跳转到登陆⻚⾯(可以把router.push()封装为跳转函数,进⾏调⽤),有的话,就响应拦截器外定义⼀个变量标记Token的刷新状态(避免多次请求刷新Token) 默认为false,和⼀个数组⽤来存储因为token刷新⽽挂起的请求,在有user信息的逻辑基础上,去if判断这个变量,为true表⽰正在进⾏刷新token的请求,另那么我们就return;
push函数,把失败请求存储到列表中去;else就是变量为false,先设置变量true,然后获取到⽤⼾信息中的续期 token的字段;作为参数发送获取新的token请求(实现⽤⼾⽆感知刷新tokan),使⽤if判断code字段!==200,失败就使⽤vuex的commit⽅法在 mutation 中清除⽆效的⽤⼾信息,然后调⽤跳转函数跳转到登陆⻚⾯去;code字段==200,成功就使⽤vuex的commit⽅法在mutation 中存储新的token,然后重新发送失败的请求(使⽤forEach遍历请求存储列表,进⾏⾃调⽤),然后就清空数组,将请求return 出去request(error.config);最后⽆论请求成功失败就把这个变量字段设置false;
32. 说⼀下项⽬的流程
答:
1.项⽬⽴项2.BA整理项⽬需求,定项⽬周期;
3. 需求评审(过项⽬需求)
4.后端设计数据库,ui设计原型图
5.ui评审
6. 前端静态⻚⾯开发(mock数据测试),后端做接⼝,测试做测试⽤例;
7. 前后端联调
8.测试
9.项⽬上线
33. 商品和增删改查
答:根据接⼝⽂档获取到已有的商品列表信息(商品名称、商品价格、商品信息),进⾏列表渲染展⽰,可以对商品进⾏增加、删除、修改。
添加:根据接⼝⽂档,发送添加请求,判断接⼝返回结果中 code 字段的 ==200就使⽤
Element-UI 的message消息提⽰,添加成功,关闭遮罩层为false,调⽤请求数据函数更新列表;else就抛出⼀个错误信息;
修改:当点击修改时,弹出 Element-UI遮罩层收集⽤⼾修改数据,这⾥进⾏了⼀个lodash浅拷⻉赋值操作(因为数据在⻚⾯上正在展⽰,直接修改数据会导致⻚⾯数据发⽣变化),点击确定的时候会,就把⽤⼾信息作为参数,发送修改请求,判断接⼝返回结果中code字段的 ==200 就使⽤ Element-UI的message消息提⽰,修改成功,关闭遮罩层为false,调⽤请求数据函数更新列表;else 就抛出⼀个错误;
删除:在删除的回调中可以拿到当前商品的id,那么就把id作为参数发送删除请求,判断接⼝返回结果中code 字段的== 200就使⽤Element-UI 的message消息提⽰,删除成功,调⽤请求数据函数来更新列表;
34. Element-UI 的form表单验证你是怎么使⽤的
答:⾸先是在form表单配置 rules 校验规则,可以在组件data中⾃定义(或者统⼀封装到⼀个Js⽂件中),使⽤required: true,来设置form表单为必填项,message设置提⽰信息,通过trigger 定义触发校验⽅式;当全部表单都符合校验规则,在点击确定的时候调⽤ validate进⾏最终的表单校验。
validate 参数为⼀个回调函数,回调函数有⼀个 config参数(是否校验成功)我们可以对config进⾏判断,成功就携带form表单的信息提交后台;
35. 项⽬中的商品详情⻚你是怎么实现的
答:当⽤⼾点击商品名字或者图⽚的时候,就进⾏this.$router.push 进⾏路由跳转并传递商品的id 到详情⻚,再通过后台提供的相关详情接⼝,把id 作为参数,在详情组件的 mounted钩⼦函数中派发action 调⽤Vuex中的请求函数,获取到商品的详细数据存储Vuex中,通过getters 配置对象,对数据进⾏简化,通过mapgetters 映射给组件,使⽤插值语法或者v-for进⾏数据的渲染;
36. 什么是数组扁平化
答:所谓的数组扁平化就是将多维数组转化为⼀维数组;
⼀般数组扁平化,数组中存储的多维数据都是数组 不会是对象或者函数;
具体实现:最常⽤的⽅法就是使⽤toString()⽅法将数组中的每⼀个数据,转成⼀个字符串,使⽤逗号进⾏间隔,再使⽤字符串中的split⽅法,以逗号进⾏分割将字符串再转化为⼀维数组;
37. 你这个项⽬登陆是怎么实现的
答:登陆的⽅式有很多种,我们这个选择两种⽅式进⾏回答。
第⼀种:⼿机号+验证码实现登陆
(1)在⽤⼾选择登陆的时候,会收集⽤⼾输⼊的信息,进⾏⼀个form的校验(正则或者Element-U⽅式,校验字段是否合法,不合法就给予错误提⽰)
(2)当⽤⼾点击获取验证码按钮的时候,发送获取验证码请求,后端会发验证码⾄⽤⼾⼿机,并对验证码设置⼀个过期时间,这时把按钮disabled设置为true变为禁⽤状态,使⽤setinterval定时器设置⼀个倒计时的效果,把按钮⽂本内容与倒计时进⾏拼接显⽰,判断这个倒计时等于0就清除这个定时器clearlnterval,解除按钮的禁⽤状态disabled设置为false,按钮⽂本恢复为获取验证码,计时变量再设置为60秒;⽤⼾收到验证码后进⾏输⼊。
(3)在点击登录的回调中,为了防⽌在输⼊验证码后⼿机号更换了或者删除了,发送⽆效请求,所以这⾥还要对⼿机号进⾏校验,不合法就提⽰⽤⼾输⼊正确⼿机号,然后return退出,合法就发送登陆请求,if判断返回请求结果成功就$router.push()跳转到⾸⻚;else登陆失败,就直接return⼀个Promise.reject()new⼀个error错误进⾏抛出;
第⼆种:账⼾+密码实现登陆
(1)收集数据,进⾏form表单验证与上⾯相同;
(2)通过监听属性调⽤后台获取公钥接⼝,(该接⼝中后台会通过算法⽣成⼀对钥匙公钥、私钥,并存到session中,公钥则返回给前端)前端拿到公钥后,再通过JS加密库中的⽅法对⽤⼾输⼊的密码进⾏加密。
(3)点击登录时,发送登录请求,传递加密好的密⽂;登录成功后,就提⽰⽤⼾登陆成功,本地存储token令牌,使⽤$router.push()跳转⾄⾸⻚;
38. 项⽬中的权限管理怎么实现的答:权限管理有三个很重要的模块;
(1)⽤⼾模块:可以给⽤⼾分配不同的⻆⾊
(2)⻆⾊模块:可以授于⽤⼾不同的⻆⾊,不同的⻆⾊有不同权限
(3)权限模块:⽤于管理系统中的权限接⼝,为⻆⾊提供对应的权限
具体实现步骤
根据⽤⼾管理中给⽤⼾分配⻆⾊的不同,就有对应的菜单权限。
(1)当⽤⼾登录后,后端会把⽤⼾token和相应的⽤⼾信息(⽤⼾名/菜单权限),返回给前端,前端会先把⽤⼾信息先进⾏保存。
(2)在routes.js路由⽂件中把路由拆分为静态路由和动态路由,在vuex的user.js模块中,通过数组的filter⽅法和indexOf定义⼀个递归函数,在请求⽤⼾信息的时候,再进⾏commit提交mutations⼀个计算函数同时调⽤递归函数传递参数(参数⼀是异步路由,参数⼆是⽤⼾的权限信息)进⾏递归过滤,留下当前⽤⼾有权限访问的路由。
(3)在mutations中,通过concat⽅法合并静态路由和过滤后的动态路由,使⽤路由的addRouter⽅法注册为新的路由,实现根据不同的⽤⼾展⽰不同的菜单侧边栏; (后端也会进⾏⼀些权限接⼝的判断和拦截,通过⾮法途径是访问不了的)
39. Vue的$nextTick()⽅法有⽤到过吗
答:有,⽐如说数据渲染更新后,我们要更后的数据进⾏某些操作时,就可以在nextTick指定的回调函数中去执⾏;
40. 深拷⻉与浅拷⻉
浅拷⻉:只是复制某个对象的指针,⽽不复制对象本⾝,新旧对象还是共享同⼀块内存;深拷⻉:会另外创造⼀个⼀模⼀样的对象,新对象跟原对象不共享内存,修改新对象不会影响到原对象;
实现浅拷⻉⽅式:1.0bject.assign;2.es6扩展运算符
实现深拷⻉⽅式:1.JSON.parse(JSON.stringify(object));2.lodash插件;
实际⼯作中:(1)当数据类型⽐较简单时(对象/数组)的时候,可以⽤浅拷⻉;(2)当数据结构中存在对象⾥⾯套数组,数组⾥⾯套对象(结构较为复杂),需要使⽤深拷⻉来解决这类问题;
lodash插件;
实际⼯作中:(1)当数据类型⽐较简单时(对象/数组)的时候,可以⽤浅拷⻉;(2)当数据结构中存在对象⾥⾯套数组,数组⾥⾯套对象(结构较为复杂),需要使⽤深拷⻉来解决这类问题;41. 在Vue是项⽬中如何打开新的⻚⾯
答:使⽤this.$router.resolve()和window.open(xxx.href,'_blank')在进⾏路由跳转的时候就会打开新的窗⼝。但是这种⽅式有个问题就是不能⽤params⽅式进⾏传递参数,在⻚⾯跳转过去后,获取的params⽅式传递参数为undefined。
解决办法:使⽤query⽅式传参,本地存储或者Vuex;
42. 请解释⼀下微前端的概念以及它的主要优点和挑战?
微前端是⼀种将不同的前端应⽤组合到⼀起的架构模式。这些应⽤可以独⽴开发、独⽴部署、独⽴运⾏,然后在⼀个主应⽤中进⾏集成。这种模式的主要⽬标是解决⼤型、⻓期演进的前端项⽬的复杂性问题。
主要优点:
1. 解耦: 微前端架构可以将⼤型项⽬分解为多个可以独⽴开发、测试和部署的⼩型应⽤。这种解耦可以提⾼开发效率,减少团队间的协调成本。
2. 技术栈⽆关: 不同的微前端应⽤可以使⽤不同的技术栈,这为使⽤新技术、升级旧技术提供了可能。
3. 并⾏开发: 因为微前端应⽤是独⽴的,所以多个团队可以并⾏开发不同的应⽤,⽆需担⼼相互影响。
4. 独⽴部署: 每个微前端应⽤可以独⽴部署,这意味着可以更快地推出新功能,同时降低了部署失败的⻛险。
主要挑战:
1. 性能问题: 如果不同的微前端应⽤使⽤了不同的库或框架,可能会导致加载和运⾏的性能问题。
2. ⼀致性: 保持不同的微前端应⽤在⽤⼾体验、设计和⾏为上的⼀致性可能会⽐较困难。
3. 状态共享: 在微前端应⽤之间共享状态可能会⽐较复杂,需要使⽤特殊的⼯具或模式。
4. 复杂性: 尽管微前端可以解决⼤型项⽬的复杂性问题,但是它⾃⾝也带来了⼀些复杂性,⽐如需要管理和协调多个独⽴的应⽤。
5. 安全性: 微前端架构可能会增加跨域等安全问题。
43. 你能详细描述⼀下 qiankun 微前端框架的⼯作原理吗?
qiankun 是⼀个基于 single-spa 的微前端实现框架。它的⼯作原理主要涉及到以下⼏个⽅⾯:
1. 应⽤加载:qiankun 通过动态创建 script 标签的⽅式加载⼦应⽤的⼊⼝⽂件。加载完成后,会执⾏⼦应⽤暴露出的⽣命周期函数。
2. ⽣命周期管理:qiankun 要求每个⼦应⽤都需要暴露出 bootstrap、mount 和 unmount 三个⽣命周期函数。bootstrap 函数在应⽤加载时被调⽤,mount 函数在应⽤启动时被调⽤,unmount 函数在应⽤卸载时被调⽤。
3. 沙箱隔离:qiankun 通过 Proxy 对象创建了⼀个 JavaScript 沙箱,⽤于隔离⼦应⽤的全局变量,防⽌⼦应⽤之间的全局变量污染。
4. 样式隔离:qiankun 通过动态添加和移除样式标签的⽅式实现了样式隔离。当⼦应⽤启动时,会动态添加⼦应⽤的样式标签,当⼦应⽤卸载时,会移除⼦应⽤的样式标签。
5. 通信机制:qiankun 提供了⼀个全局的通信机制,允许⼦应⽤之间进⾏通信。
44. 在使⽤ qiankun 时,如果⼦应⽤是基于 jQuery 的多⻚应⽤,你会如何处理静态资源的加载问题?
在使⽤ qiankun 时,如果⼦应⽤是基于 jQuery 的多⻚应⽤,静态资源的加载问题可能会成为⼀个挑战。这是因为在微前端环境中,⼦应⽤的静态资源路径可能需要进⾏特殊处理才能正确加载。这⾥有⼏种可能的解决⽅案:
⽅案⼀:使⽤公共路径
在⼦应⽤的静态资源路径前添加公共路径前缀。例如,如果⼦应⽤的静态资源存放在
http://localhost:8080/static/ ,那么可以在所有的静态资源路径前添加这个前缀。⽅案⼆:劫持标签插⼊函数
这个⽅案分为两步:
1. 对于 HTML 中已有的 img/audio/video 等标签,qiankun ⽀持重写 getTemplate 函数,可以将⼊⼝⽂件 index.html 中的静态资源路径替换掉。
2. 对于动态插⼊的 img/audio/video 等标签,劫持 appendChild、innerHTML、insertBefore 等事件,将资源的相对路径替换成绝对路径。
45. 在使⽤ qiankun 时,如果⼦应⽤动态插⼊了⼀些标签,你会如何处理?
在使⽤ qiankun 时,如果⼦应⽤动态插⼊了⼀些标签,我们可以通过劫持 DOM 的⼀些⽅法来处理。例如,我们可以劫持 appendChild 、 innerHTML 和 insertBefore 等⽅法,将资源的相对路径替换为绝对路径。
46. 在使⽤ qiankun 时,你如何处理⽼项⽬的资源加载问题?你能给出⼀些具体的解决⽅案吗?
在使⽤ qiankun 时,处理⽼项⽬的资源加载问题可以有多种⽅案,具体的选择取决于项⽬的具体情况。以下是⼀些可能的解决⽅案:
1. 使⽤ qiankun 的 getTemplate 函数重写静态资源路径:对于 HTML 中已有的
img/audio/video 等标签, qiankun ⽀持重写 getTemplate 函数,可以将⼊⼝⽂件
index.html 中的静态资源路径替换掉。
2. 劫持标签插⼊函数:对于动态插⼊的 img/audio/video 等标签,我们可以劫持
appendChild 、 innerHTML 、 insertBefore 等事件,将资源的相对路径替换成绝对路径。例如,我们可以劫持 jQuery 的 html ⽅法,将图⽚的相对路径替换为绝对路径:
3. 给⽼项⽬加上 webpack 打包:这个⽅案的可⾏性不⾼,都是陈年⽼项⽬了,没必要这样折腾。
4. 使⽤ iframe 嵌⼊⽼项⽬:虽然 qiankun ⽀持 jQuery ⽼项⽬,但是似乎对多⻚应⽤没有很好的解决办法。每个⻚⾯都去修改,成本很⼤也很⿇烦,但是使⽤ iframe 嵌⼊这些⽼项⽬就⽐较⽅便。
47. 你能解释⼀下 qiankun 的 start 函数的作⽤和参数吗?如果只有⼀个⼦项⽬,你会如何启⽤预加载?
qiankun 的 start 函数是⽤来启动微前端应⽤的。在注册完所有的⼦应⽤之后,我们需要调
⽤ start 函数来启动微前端应⽤。
start 函数接收⼀个可选的配置对象作为参数,这个对象可以包含以下属性:
• prefetch :预加载模式,可选值有 true 、 false 、 'all' 、 'popstate' 。默认值为 true ,即在主应⽤ start 之后即刻开始预加载所有⼦应⽤的静态资源。如果设置为'all' ,则主应⽤ start 之后会预加载所有⼦应⽤静态资源,⽆论⼦应⽤是否激活。如果设置为 'popstate' ,则只有在路由切换的时候才会去预加载对应⼦应⽤的静态资源。
• sandbox :沙箱模式,可选值有 true 、 false 、 { strictStyleIsolation: true} 。默认值为 true ,即为每个⼦应⽤创建⼀个新的沙箱环境。如果设置为 false ,则⼦应⽤运⾏在当前环境下,没有任何的隔离。如果设置为 { strictStyleIsolation: true } ,
则会启⽤严格的样式隔离模式,即⼦应⽤的样式会被完全隔离,不会影响到其他⼦应⽤和主应⽤。
• singular :是否为单例模式,可选值有 true 、 false 。默认值为 true ,即⼀次只能有⼀个⼦应⽤处于激活状态。如果设置为 false ,则可以同时激活多个⼦应⽤。
• fetch :⾃定义的 fetch ⽅法,⽤于加载⼦应⽤的静态资源。
48. axios-请求中post请求的坑
刚开始的坑是,使⽤axios的post⽅法请求数据,数据被拦截,数据⼀直传不到后端那边。后来查⽂档才得知 axios对于post请求是有拦截功能的,需要⾃⼰判断,或者使⽤提请的 qs ⽅法,将传给后端的数据进⾏下处理。
49. 路由传参的功能的坑
之前⼀直使⽤路由传参,但是当本⻚⾯刷新的时候,⻚⾯上是没有参数的,因为参数是从上个⻚⾯传⼊进来的。 解决办法:使⽤了缓存,和vuex状态管理。但是由于项⽬并不是很⼤型的项⽬,所以使⽤最多的是缓存。
50. ⻚⾯缓存的坑
有个填写信息的⻚⾯,需要填写⼀部分信息,进⼊查新协议⻚⾯,返回的时候,⻚⾯上填写的信息还需要留存。 解决办法:使⽤vue提供的keep-alive,来完成⻚⾯的缓存的。
结尾
因为文章全写出来就太长了,目前来说,后面还有相当多,觉得对大家有帮助的话,可以直接T我或者【点击此处】
更多的场景题、简历模板之类的也可以,都是个人整理!