前端面试题记录(偶尔更新)

总结最近招聘面试时,经常会问的一些关于Vue的问题。

  1. vue的data为什么是个函数?
      data是Vue的数据对象,Vue会递归的把data的property转换为setter/getter,让property能相应数据变化。
      个人理解:
      这个问题主要是针对于Vue2的,对于Vue3采用的方法的组合调用来完成组件的定义。data改为了var data = ref([1, 2, 3])的形式
      按照Vue教程来看,教程上确实是写的data是对象,这是因为教程是在HTML中通过new Vue使用的,Vue本身new之后都会是一个新对象,不存在共用对象的问题。
      但是在单页面应哟.vue文件中使用时,当一个组件被实例化的时候,会通过data获取数据对象。如果data是一个函数,则调用data函数时会返回一个全新的对象,保证同一个组件被多次实例化后都独立维护自己的数据对象。如果data是一个对象,组件多次实例化后会共享同一套数据对象。

  2. vue生命周期有哪些?
      beforeCreate:在实例初始化之后,只是基础加载 data和dom都不可用
      created:实例已经创建完成之后被调用,data,method等都可用,dom不可用,可以使用nextTick访问dom。一般数据请求都放在这里
      beforeMounted:组件挂载之前调用
      mounted:组件挂载完成之后调用dom加载完成,双向绑定生效
      beoreUpdate:数据更新时调用,虚拟dom重新渲染之前调用
      updated:数据更新完成,要避免在这里更新数据,防止出现循环更新
      beforeDestory:实例销毁之前调用
      destory:实例销毁完成调用
      activated:keep-alive专属生命周期,组件被激活时调用
      deactivated:组件被销毁时调用

  3. computed和watch区别是什么?
      computed是计算属性,依赖其他属性进行计算并返回计算结果。具有缓存机制,如果依赖的属性没有变更,则每次都是从缓存中取数据。
      watch是监听,可以监听某一个属性的变化并执行自定义的一系列操作。
      computed相比于method多了缓存机制,method里面的方法不具有缓存逻辑,每次调用方法都是执行内部的业务逻辑

  4. v-if和v-for为什么不建议一起用?
      v-if和v-for的优先级不同,v-for的优先级会高于v-if。
      可以利用计算属性computed 对list进行计算解析,过滤出需要的内容再进行v-for循环。

  5. vue双向绑定方式有哪些?
      v-model和.sync修饰符。
      v-model是变成value和input的语法糖,主要是通过vue的mode属性结合event事件实现的,一般只能绑定一个属性。
      .sync修饰符主要是使用update:函数实现的,可以绑定多个属性。

  6. 为什么用虚拟dom?
      在底层实现上,Vue将模板编译成虚拟dom渲染函数。结合相应系统,vue能智能的算出最少要重新渲染多少组件,并把dom操作次数减到最少。

  7. 虚拟DOM是什么?有什么优缺点?
      由于在浏览器中操作DOM是很昂贵的。频繁操作DOM,会产生一定性能问题。这就是虚拟Dom的产生原因。Vue2的Virtual DOM 借鉴了开源库 snabbdom 的实现。Virtual DOM本质就是用一个原生的JS对象去描述一个DOM节点,是对真实DOM的一层抽象。
      优点:
      (1). 保证性能下限:框架的虚拟DOM需要适配任何上层API可能产生的操作,他的一些DOM操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的DOM操作性能要好很多,因此框架的虚拟DOM至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,既保证性能的下限。
      (2). 无需手动操作DOM:我们不需手动去操作DOM,只需要写好 View-Model的 代码逻辑,框架会根据虚拟DOM和数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率。
      (3).跨平台:虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器端渲染、weex开发等等。
      缺点:
      (1). 无法进行极致优化:虽然虚拟DOM + 合理的优化,足以应对大部分应用的性能需要,但在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化。
      (2).首次渲染大量DOM时,由于多了一层DOM计算,会比innerHTML插入慢。

  8. 你都做过哪些 Vue 的性能优化?
      * 对象层级不要过深,否则性能就会差。
      * 不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
      * v-if 和 v-show 区分使用场景
      * computed 和 watch 区分场景使用
      * v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
      * 大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
      * 防止内部泄露,组件销毁后把全局变量和时间销毁
      * 图片懒加载
      * 路由懒加载
      * 异步路由
      * 第三方插件的按需加载
      * 适当采用 keep-alive 缓存组件
      * 防抖、节流的运用
      * 服务端渲染 SSR or 预渲染

  9. 前端优化主要从那些方面考虑?
      * 降低请求量:合并资源,减少HTTP请求数,minify/gzip压缩
      加快请求速度:预解析DNS,减少域名数,并行加载
      
    缓存:HTTP协议缓存请求,离线缓存manifest,离线数据缓存localStorage
      * 渲染:JS/CSS优化,加载顺序,服务端渲染

  10. 浏览器运行机制是什么?
      (1). 创建DOM树
      (2). 构建渲染树,CSS渲染
      (3). 布局渲染,每个元素的大小、位置
      (4). 绘制渲染树、再画出来
    重绘:改变元素的外观属性例如div的color、background-color、等属性发生改变时
    重排(回流):元素的规模尺寸、布局、隐藏改变时
    代价:耗时,导致浏览器卡慢

  11. 优先级由高到低: props ==> methods ==> data ==> computed ==> watch

  12. key的作用
      key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
    (key主要是用来虚拟dom计算。不使用key时,利用响应式系统计算dom操作次数。使用key时,基于key的变化重新排序,并移除key不存在的元素)
      有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
      用在v-for中提供跟踪每个节点的身份,从而重用和重新排序现有元素。
      key是一个唯一标识,如果使用index作为key,当数组index变更,比如增删时。index之后的所有dom节点都会更新。

  13. 作用域插槽的原理
    https://blog.csdn.net/qq_44166697/article/details/108274625
      slot本质上是返回VNode的函数,一般情况下,Vue中的组件要渲染到页面上需要经过template>>render function >> VNode >> DOM过程。组件挂载的本质就是执行渲染函数得到VNode,至于data/props/computed这些属性都是给VNode提供数据来源
      在2.5之前,如果是普通插槽就直接是VNode的形式了,而如果是作用域插槽,由于子组件需要再父组件访问子组件的数据,所以父组件下是一个未执行的函数(slotScopre) => return h('div',slotScope.msg),接受子组件的slotProps参数,在子组件渲染实例时会调用该函数传入数据。
      在2.6之后,两者合并,普通插槽也变成一个函数,只是不接受参数了

  14. 为什么避免在模板或计算属性中访问$refs

  $refs只会在组件渲染完成后生效,并且他们不是响应式的。这仅作为一个用于直接操作子组件的”逃生舱“

  1. 依赖注入provide。inject问题
      它将你应用程序中的组件与它们当前的组织方式耦合起来,使重构变得更加困难。同时所提供的 property 是非响应式的

  2. 为什么数据请求要建议放到created生命周期?
      Created在实例创建完成后同步调用。在这一步中,实例已完成对选项的处理,意味着数据侦听、计算属性、方法、事件/侦听器的回调函数已被配置完毕。

  3. assets、static、public区别
      public:放一些静态资源,比如html的js,打包是会直接打入dist中
    相同:assets、static都可以放一些资源。
      不同:
      (1). assets会经过webpack打包,占用资源更少,static不会,会直接复制到dist文件夹中。
      (2). 但在动态绑定中,assets路径的图片会加载失败,因为webpack使用的是commenJS规范,必须使用require才可以
      (3). static/目录下的文件都应该是使用绝对路径,assets使用相对路径。
      绝对路径:是指文件在硬盘上真正存在的路径。 /desktop/page/..
      相对路径:就是相对于自己的目标文件位置。 “.././“
    static中建议放一些外部第三方,自己的放到assets,别人的放到static中

18、深拷贝方式
(1)JSON对象
(2)递归
(3)$.extends

// 递归示例
deepClone(obj){
    let newObj = Object.create(null)
    for (let k of Object.keys(obj)){
        newObj[k] = obj[k]
    }
    return newObj
}
  1. 什么是响应式
      数据是可以进行观测的,也就是说在读取和设置的时候可以劫持他来做其他操作。响应式和视图没关系,他只是一种机制,一种侦测数据变化的机制。

  2. Vue2和Vue3实现双向绑定原理
      Vue2:基于Object.defineProperty 修改对象属性的权限标签
      Vue.js一个核心思想是数据驱动****。所谓的数据驱动是指视图是由数据驱动的,对视图的修改不会直接操作Dom,而是通过修改数据。Vue.js里面只需要改变数据,Vue.js通过Directives指令去Dom做封装,当数据发生变化,会通知指令去修改对应的Dom,数据驱动Dom的变化,Dom是数据的一种自然的映射。Vue.js还会对View操作做一些监听(Dom Listener),当我们修改视图的时候,vue.js坚定提到这些编号,从而改变数据。这就形成了双向绑定。
      官方解释:

当你把一个普通的JS对象传入Vue实例作为data选项,Vue会递归遍历此对象所有的property,并使用Object.defineProperty把这些property全部转换为getter/setter。
这些getter/setter对用户来说是不可见的,但是在内部他们让Vue能够跟踪依赖,在property被访问和修改时通知变更。
每个组件实例都对应一个watcher实例,他会在组件渲染的过程中把“接触”过的数据property记录为依赖,之后当依赖项的setter触发时,会通知watcher,从而改变关联的组件重新渲染。

  defineProperty是ES5中的一个无法shim的特性,这也是Vue不支持IE8以下版本的原因。
  个人理解:
  通过Object.defineProperty递归的为对象增加setter/getter。并通过watcher监听数据变化,并改变关联的组件重新渲染。

  Vue3:基于ES6的Proxy 代理整个对象
  在vue3中则是使用es6 proxy代理,将对象data进行转化拦截,使用weakMap做弱引用缓存。当触发代理的get时就会调用track,在track里面会把对应的effect收集到targetMap(targetMap就是map数据)
  set时会执行trigger,trigger函数如果有获取有对应的effect,就会触发effect。

  问题扩展
  Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
  一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。
  Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。

  vue3优点
  Vue3优化diff算法。不再像vue2那样比对所有dom,而采用了block tree的做法。此外重新渲染的算法里也做了改进,利用了闭包来进行缓存。这使得vue3的速度比vue2快了6倍。

  1. ES6新增内容。
      ES6增加了let、const、Map、Set、Symbol、Reflect和Proxy。对于字符串,对象,数组、函数之类的增加了一些方法。增加了Promise对象,async函数、Generator函数等,增加了export导出模块。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容