前一段写了篇Vue.js 常见面试题【基础类】 – 码中人,今天补齐扩展类问题。

vue.js常见面试题【扩展类】_java

1.请谈谈对于MVVM的理解?

如果你很了解mvc,可以从mvc开始答起。

MVVM前端界面分成三部分:Model、View、ViewMode。

  • Model:代表数据模型,数据和业务逻辑都在Model层中定义;

  • View:代表UI视图,负责数据的展示;

  • ViewModel:负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作;

其中MVVM的显著特点就是双向绑定. view的变动会自动更新到Model中。

vue.js常见面试题【扩展类】_java_02


2.第一次页面加载会触发哪几个钩子?

所谓钩子函数(hook function),指的是框架或应用程序提供一些挂钩,方便开发者在某一时刻将自己实现的功能挂接到目标挂载点上。

你可以简单理解为,钩子函数是程序中预定义好的函数,而你写了一个同名函数覆盖它,程序执行时,会执行你的自定义函数。

Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

vue实例生命周期官方示意图如下:

vue.js常见面试题【扩展类】_java_03

生命周期内暴露出8个钩子函数(创建前/后, 载入前/后,更新前/后,销毁前/销毁后):

  • beforeCreate

  • created

  • beforeMount

  • mounted

  • beforeUpdate

  • updated

  • beforeDestroy

  • destroyed

第一次加载vue实例会触发:beforeCreate、created、beforeMount、mounted这四个钩子函数。


3.DOM渲染在哪个生命周期中完成?

首先,什么是生命周期?

Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

DOM 渲染在 mounted 中就已经完成了。


4.Vue实现数据双向绑定的原理

Vue实现数据双向绑定主要利用的就是: 数据劫持和发布订阅模式。
所谓发布订阅模式就是,定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。

所谓数据劫持,就是利用JavaScript的访问器属性,即Object.defineProperty()方法,当对对象的属性进行赋值时,Object.defineProperty就可以通过set方法劫持到数据的变化,然后通知发布者(主题对象)去通知所有观察者,观察者收到通知后,就会对视图进行更新。

参考资料:Vue双向绑定原理,教你一步一步实现双向绑定 – 知乎


5.Vue组件间的参数传递

  • 父传子:props

  • 子传父:$emit。父组件给子组件绑定一个事件名A事件处理函数AHandle,子组件触发该事件名A,执行父组件AHandle(各种语法糖)

  • 异父异母:EventBus

  • 异父异母:Vuex

当然,Vuex/EventBus也可用于父子、兄弟组件。


6.Vuex是什么?怎么使用?哪种功能场景使用它?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex有5种属性: 分别是 state、getter、mutation、action、module;其中:

  • 只用来读取的状态集中放在store中;

  • 改变状态的方式是提交mutations,这是个同步的事物;

  • 异步逻辑应该封装在action中。

怎么使用使用?

在main.js引入store,注入。

新建了一个目录store,… export

场景有:

单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车

参考资料:vuex是什么?怎么使用?哪种功能场景使用它?_LuckXinXin的博客-CSDN博客_哪种功能场景使用vuex


7.虚拟DOM的优缺点?

虚拟Dom指的是用js模拟一颗DOM树,放在浏览器的内存中,当需要变更时,虚拟DOM进行diff算法进行新旧虚拟DOM的对比,将变更放入到队列中。反应到实际的DOM上,减少DOM的操作。

虚拟DOM将DOM树转换成一个JS对象树,diff算法逐层比较,删除,添加操作,但是,如果有多个相同的元素,可能会浪费性能,所以,react和vue-for引入key值进行区分.

优点:

  • 保证性能下限:框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;

  • 无需手动操作 DOM:我们不再需要手动操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;

  • 跨平台:虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。

缺点:

  • 无法进行极致优化:虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

  • 首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。


8.Vue与React的选择

如果上一个项目用Vue做的,那么这一个项目就优先用React。

小孩才做选择,成年人哪里有得选?


9.Vuex中mutation和action的详细区别

action:简单来说就是异步操作数据

mutation:把处理数据逻辑方法全部放在mutation里面使数据和视图分离(vuex中store数据改变唯一的方法就是mutation)

流程顺序

“相应视图—>修改State”拆分成两部分,视图触发Action,Action再触发Mutation。

角色定位

基于流程顺序,二者扮演不同的角色。

Mutation:专注于修改State,理论上是修改State的唯一途径。

Action:业务代码、异步请求。

限制

角色不同,二者有不同的限制。

Mutation:必须同步执行。

Action:可以异步,但不能直接操作State。


10.简述Vue的diff算法原理

DOM渲染的开销是很大的,有时候我们修改了某个数据,直接渲染到真实dom上会引起整个dom树的重绘和重排。diff算法就是帮助我们只更新我们修改的那一小块dom而不要更新整个dom。

我们先根据真实DOM生成一颗 virtual DOM ,当 virtual DOM 某个节点的数据改变后会生成一个新的 Vnode ,然后 Vnode 和 oldVnode 作对比,发现有不一样的地方就直接修改在真实的DOM上,然后使 oldVnode 的值为 Vnode 。

vue.js常见面试题【扩展类】_java_04

diff的过程就是调用名为 patch 的函数,比较新旧节点,一边比较一边给 真实的DOM 打补丁。

总结

1.diff算法是虚拟DOM技术的必然产物:通过新旧虚拟DOM作对比(即diff),将变化的地方更新在真实DOM上;另外,也需要diff高效的执行对比过程,从而降低时间复杂度为O(n)。

2.vue2.x中为了降低Watcher粒度,每个组件只有一个Watcher与之对应,只有引入diff才能精确找到发生变化的地方。

3.vue中diff执行的时刻是组件实例执行其更新函数时,它会比对上一次渲染结果oldVnode和新的渲染结果newVnode,此过程称为patch。

4.diff过程整体遵循深度优先、同层比较的策略;两个节点之间比较会根据它们是否拥有子节点或者文本节点做不同操作;比较两组子节点是算法的重点,首先假设头尾节点可能相同做4次比对尝试,如果没有找到相同节点才按照通用方式遍历查找,查找结束再按情况处理剩下的节点;借助key通常可以非常精确找到相同节点,因此整个patch过程非常高效。

diff的流程如下:

vue.js常见面试题【扩展类】_java_05

参考资料:用vue想拿20k,面试题要这样答!–第四集 怎么理解vue中的diff算法_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili