面试题逐字稿
回答问题的重点:
① 明确面试官的问题,不清楚可以追问,避免回答不在点上。
② 回答问题有条理有逻辑,建议按照总分方式。
③ 技术问题最好有理有据、言之有物。先说场景,再说思路,再说具体解决方案。
一、问: axios 有没有做过一些业务封装?
有的。在项目里面主要是封装过 axios 的拦截器部分。我在请求拦截器里面做了注入全局 token 的事情,这个事儿是因为有很多接口都需要这个 token 来做数据鉴权,为了避免书写多次 统一配置了一下。
还有在响应拦截器的部分,主要是做了一个自定义的错误判断这个事儿,因为我们知道拦截器的成功和失败判断本身是通过 http 状态码 200- 300 ,可以在响应拦截器的第一个回调函数中对成功的响应做处理,比如在第一个回调函数中对响应回来的数据去掉一层,只返回响应结果的 data,这样在组件中就可以直接获取到后端返回的数据。在第二个回调函数中对失败的响应做处理,比如在第二个回调函数中对错误进行统一提示。
二、问:未登录的用户,手动输入项目中的路由,能不能跳转过去?
不能跳转。可以使用 vue 的全局前置守卫做判断,我们可以在前置守卫里拿到 token 数据,然后根据需求做分支判断,要是 token 存在就使用 next 方法正常放行跳转,否则可以强制跳回到登录,让用户去获取 token。
追问: 但 token 有一定的时效性,过期了该怎么做?
token 失效之后后端会返回前端一个 401 的状态码,我们可以在 axios 的响应拦截器里,去获取这个状态,如果发现是 401 就清理一下过去的 token,然后重新跳转到登录页,重新登录获取有效 token。
三、excel 导出功能的实现流程简要描述一下?
导出的话,我们因为到处的数据量不大,所以直接采取的时候前端主导的方案,参考的现成方案实现的导出
大概得流程就是
1调用后端接口得到要导出的数据
2把数据简单处理一下转化成导出插件需要的格式
3把数据配置到对应的位置就行
使用xlsx插件会自动帮助我们生成excel文件并且自动下载到本地
追问: 那如果要导出的数据量比较大怎么解决?
那可能一开始就要采用后端主导的方案了,我们可以把这个excel文件生成的过程放到服务器去做,前端只需要调用一个下载接口,把后端准备好的excel文件下载到我们本地就行
四、问: 有做过权限相关的事情吗?
有做过,我们前端这边主要做的就是菜单权限控制和按钮显示控制,权限的最小粒度控制到按钮权限
追问: 说说菜单权限怎么做的?
权限设计是一个需要前后端配合的事情,大概分成下面几个步骤 1.做权限之前,后端会出一个权限标识和菜单还有按钮的一个对照表 2.需要做权限控制的菜单 单独放在动态路由中。路由规则中应该有个属性和后端返回的权限标识是对应的(比如给路由规则添加个permission属性,或者在路由规则meta属性中新增个值都可以) 3.把后端返回的权限数据和前端本地的路由规则对应的那个值做对比(比如跟permission属性的值做对比),得到过滤之后的有资格显示的路由数组 4.调用路由核心方法router.addRoute把路由数组加入到路由系统中(addRoute添加的是有权限才能看到路由,所以即使用户记住了一些项目中的url也不怕) 5.最后把可现实的路由展示到左侧菜单里。因为$router.options.routes拿不到addRoute添加之后的路由。所以可以把可显示的路由规则存到vuex中一份,取vuex中的数据渲染左侧的菜单
追问: 按钮的权限又怎么做呢?
按钮的权限其实就是控制按钮的显示隐藏 思路就是通过后端返回的权限标识和按钮自身的标识做对比。如果有资格就显示,否则就移除按钮 这里根据思路我们可以封装一个全局指令,通过指令可以实现复用,就可以在需要控制的按钮身上进行指令绑定,从而控制按钮的显示和隐藏,隐藏的话就把按钮从页面中移除
五、问: 有没有封装过一些自己的业务组件,简单说一下?
有的,当开发时遇到一个模块如果复用性比较高或者业务逻辑比较复杂的模块,就会进行组件的封装。我挑一个比较简单的说一下吧,之前做业务的时候有遇到过 多个业务模块用到了类似的模板结构,就使用插槽封装了一些组件 大概的封装思路就是先把可复用的模板部分写好,然后把可变的需要自定义的部分用slot插槽占位 要是插槽个数比较多的话,可以区分一下默认插槽和具名插槽,尤其是功能区域比较明显的部分,用具名会更加清晰。还需要注意的是根据业务场景看组件是否需要通过props暴露出来一些参数,让父组件传递过去。还有子组件要不要给父组件暴露自定义事件,让父组件监听
六、问:环境变量是什么?有没有用过
环境变量是用来配置不同环境所对应的不同接口,因为公司有几个不同的环境,开发环境、测试环境、正式环境。一个环境对应前端一个环境变量文件,这几个环境变量文件都是以.env开头,且里边的变量要求必须以VUE_APP_开头。同样一个环境变量比如说VUE_APP_URL可以在不同的文件里配置不同的接口地址,再配合package.json中的命令,通过--mode参数指定一下运行的环境变量文件的后缀名就可以读取不同的环境变量文件了
七、问: 业务中的跨域问题是如何解决的?
解决跨域这个问题可以由前端解决也可以由后端或运维解决。 大部分情况下由后端或者运维解决比较方便。之前我们开发的项目也有前端解决的,如果前端来解决可以通过配置webpack的devServe中的proxy来配置。把需要请求的最终路径配置到proxy的target配置项中,这样就可以解决跨域了。但webpack解决跨域只能解决开发环境的跨域问题,因为上线后就没有webpack了 后端解决可以在响应头中配置cors来解决 运维可以通过配置nginx来解决
追问:proxy代理方案的原理是什么?
跨域的产生原因其实就是浏览器和服务器的三要素(协议、域名、端口)不一致,加上浏览器同源策略导致的,如果我可以在前端和接口端之间架设一台之间服务器,保证它和前端三要素一致,因为服务器对服务器不存在跨域 就可以解决这个问题
追问: 那你了解跨域产生时,数据到底有没有发出去?
事实上数据是能发送到服务端的,那边也能接收到请求,只不过数据在返回客户端的时候被浏览器给拦截了
八、问: 有没有开发过一些vue插件?举例说说
有过,项目开发的时间长了,沉淀了不少业务通用全局组件,想把他们统一进行注册,就封装了一个小插件 当时其实一开始也没有什么思路,后来扒了一下 elementUI的源码,仿了一下它的写法,流程我还大概记得 先是把所有的组件放到一个js文件中,然后在插件的install方法中调用Vue.component方法依次注册 最后在main.js里引入插件,通过Vue.use()进行插件注册
追问: 你如何理解vue插件,什么事儿可以用插件来做?
其实我理解的所谓插件就是vue做一些全局的拓展,增加一些它本来没有的功能 你比如添加一些静态的全局方法,再比如在原型上挂载一些实例属性,或者注册一些全局组件或者指令都算 总的说来,反正只有你能通过Vue构造函数能做到的事儿基本上都可以搞成插件
九、问: 工作中有做过数据处理吗?
主要是在组件和后端返回的数据之间,或者组件产生的数据和需要提交给后端的数据之间,有可能会出现结构对不上,这个时候可能会处理一下,举个例子,比如说我们常用的tree型组件要求必须是嵌套的tree型数组,这个时候就需要处理一下,再比如提交的时候接口要求的是字符串,我们组件给到的数组,也需要处理
追问: 既然说到了树形处理,说一下处理的思路
树形数据处理,通常后端那边返回的格式是一个普通的平铺结构,不过一般都会有一个pid字段,可以根据它找到自己的父节点,那办法就有了,或者使用递归的方式,性能好一点的话可以采用非递归的方式都可以,主要还是一个寻找父节点的过程
继续追问: 详细说说呢,伪代码思路是怎么样子的?
我们可以按照下面的步骤去写这个处理函数 1.可以先遍历原数组以它的id作为key,本身作为value形成一个对象结构 2.再次遍历原数组,通过每一项的pid字段取第一步形成的对象中尝试进行对象取值,如果取到了值就把自己push到它chilren属性中,如果找不到代表它本身就是最外层的父节点,直接push到函数最终产出的数组中
十、谈谈你对微前端的理解
微前端是一种软件架构的概念,它旨在将前端应用程序拆分为更小的、相互独立的部分,这些部分可以独立地开发、测试和部署。每个部分都可以由不同的团队开发和维护,从而提高了应用程序的可维护性和可扩展性。 微前端的核心思想是将前端应用程序拆分为多个子应用程序,每个子应用程序都可以独立地开发、测试和部署。这些子应用程序可以在同一个页面上共存,并相互之间可以进行通信和交互。这种方式可以让前端应用程序更加灵活和可扩展,可以更好地满足不同的业务需求。 微前端的实现方式常用的有乾坤、无界 微前端的优点包括:
- 灵活性:可以让前端应用程序更加灵活和可扩展,可以更好地满足不同的业务需求。
- 可维护性:可以将前端应用程序拆分为多个子应用程序,每个子应用程序都可以独立地开发、测试和部署,从而提高了应用程序的可维护性。
- 团队协作:可以让不同的团队独立地开发和维护不同的子应用程序,从而提高了团队协作的效率。
微前端的缺点包括:
- 复杂性:微前端需要使用复杂的技术和工具来实现,需要考虑到不同子应用程序之间的通信和交互,这会增加开发和维护的复杂性。
- 安全问题:由于微前端允许在同一个页面上共存不同的子应用程序,因此可能会带来安全隐患,需要进行严格的安全控制
所以选择微前端的时候,一定要根据业务场景来选择,不要为了用而用,使用不当反而带来负担。