前端面试题

  • VUE篇
  • 双向绑定的原理?
  • vue的生命周期有哪些?
  • computed和watch的区别?
  • 对keep-alive的理解
  • vue性能优化方案


VUE篇

双向绑定的原理?

vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过 object.defineproperty劫持各个属性的setter和gettr,在数据 变动时发布消息给订阅者,触发相应的的监听回调。

vue的生命周期有哪些?

生命周期

发生了什么

beforeCreate

初始化界面前:在当前阶段data,methods,computed,watch上的数据和方法都不能被访问

created

初始化界面后:在实例创建完成后发生,当前阶段已经完成了数据观测,即可以使用数据。更改数据,在这里改数据不会触发updated函数,即不会更新视图,SSR可以放在这里

beforeMount

挂载前:完成模版编译,虚拟DOM已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated

mounted

挂载完成:将编译好的模板挂载到页面(虚拟DOM挂载),可以在这里进行异步请求以及DOM节点的访问,在vue用$ref操作

beforeUpdate

更新数据前:组件数据更新之前调用,数据都是新的,页面上的数据是就的,组件即将更新,准备渲染页面,可以在当前阶段进行更改渲染,不会造成重渲染

updated

组件更新后:render重新渲染,此时数据和界面都是新的,要注意的是避免在次期间更改数据,因为这可能导致无限循环的更新

beforeDestroy

组件卸载前:实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这是进行善后收尾工作,比如清楚计时器

destroyed

组件卸载后:组件已被拆解,数据绑定被卸除监听被移出,子实例也都被销毁

activited

keep-alive 专属,组件被激活时使用

deactivated

keep-alive 专属,组件被销毁时调用

computed和watch的区别?

  1. 计算属性computed
  • 支持缓存,只有依赖数据发生改变才会重新计算
  • 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
  • computed属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
  • 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
  • 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
  1. 侦听属性watch
  • 不支持缓存,数据变,直接会触发相应的操作;
  • watch支持异步;
  • 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
  • 当一个属性发生变化时,需要执行对应的操作;一对多;
  • 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数。immediate:组件加载立即触发回调函数执行;deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。

当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。这是watch和computed最大的区别

对keep-alive的理解

在开发中,有部分组件没有必要多次初始化时,需要将组件持久化,使组件状态维持不变,在下一次展示时,也不会进行重新初始化组件。即keep-alive是vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。也就是组件缓存。

vue性能优化方案

  1. 均衡页面加载文件的大小和数量
  • 项目中小图片图片转base64,通过工具如webpack进行图片压缩,文件进行压缩混淆等
  • vue-router 懒加载,异步路由
  • 第三方依赖按需加载,比如使用element-ui框架,但是里面的组件只用到了其中一部分,可以单独建一个引入element组件的文件,在里面引入我们项目中需要的组件,然后vue.use它
  • 通过webpack进行处理,有一个externals属性,可以在里面设置不需要打包的文件,比如可以设置将vue、vue-router、element-ui等等设置进去,打包的时候就不会打包他们,然后将vue、vue-router、element-ui等资源在html中引入
  • 可以借助开启gzip压缩文件,减小文件大小;
  • 生产环境build时不生成map文件
  1. 减少等待通过xhr获取数据的时间
  • 在redis中添加缓存
  • 在并发允许且数据量较多的情况下,分页可以交给后端做,利用数据库进行排序后取出需要的分页内容,这样虽然增加了xhr请求,但是单次请求耗费时间会大大降低;后端分页每次取数据不一定是仅取当前分页的数据,可以一次性取当前页以及当前页的前后各两页的数据,这样用户进行前后页的切换时,不需要重新继续发起xhr请求。
  • 一些内容固定的数据(但又需要进行管理),可以将这些数据的获取合并为一个请求,每次刷新只需要取一次
  • 提前发起xhr请求:可以在dom渲染完成之前就发起xhr请求,而不是等待dom渲染完成之后才进行。created时,或者beforeRouteEnter时就调用。
  1. 通过交互,在视觉效果上提升
  • 可以通过一些加载loading动画,以及资源加载完成前,可以通过占位符占位的方式,避免渲染时出现空白页,视觉上提升加载速度
  • 优先加载当前用户可视区域的内容,其他内容待用户切换tab或者滚动鼠标或者可视区域加载完成后再继续加载
  • 图片预渲染,可以在当前页上根据页面上的跳转链接(或者tab页可能的切换),预渲染一些图片
  1. 使用vue的一些属性
  • v-if与v-show根据具体业务场景适当选取
  • 善用kee-alive
  1. 将项目根据业务和模块改造为多页面,而不是仅靠单页面支撑
  2. 代码优化
  • 一些前端能做的事情,可以在前端本地做,比如当分页是前端分页的时候,伴随的一些排序、筛选等,也可以由前端实现,节省xhr请求,减少时间损耗
  • 通用方法封装为模块,减少代码冗余
  • 写一些性能高的代码