【面经系列】Vue面经

【Q1】谈谈你对 MVVM 的理解

MVVMModel-View-ViewModel 的缩写,其中:

  • Model 代表数据模型,可以在 Model 中定义数据修改和操作的业务逻辑。可以把 Model 称为数据层,因为它仅仅关注数据本身,不关心其他行为。
  • View 是用户操作的界面,可以称为视图层。负责视图展现工作。当 ViewModelModel 进行更新的时候,会通过数据绑定更新到 View
  • ViewModel 称为业务逻辑层,是数据层和视图层通信的桥梁。View 需要什么数据,ViewModel 要提供这个数据,有些操作也需要 ViewModel 的响应。

【总结】:MVVM 模式简化了界面与业务的依赖,解决了数据频繁更新。在 MVVM 中,利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动更新。

【Q2】谈谈你对SPA的理解

SPA 应用仅在页面首次初始化时加载相应的 HTMLCSSJS 。一旦完成加载,就不会因为用户的操作而进行页面的重新加载,取而代之的是利用前端路由实现内容的变换。

【优点】:

  • 前后端职责更好的分离,架构清晰
  • 用户体验好,服务器相对压力小

【缺点】:

  • 首次加载耗时久
  • SEO 难优化

【Q3】谈谈你对响应式的理解

通过数据模型(普通的 JS 对象)来驱动视图的更新,就是响应式。

以实例的 data 选项为例,当我们把一个普通的 JS 对象传入 Vue 实例作为 data 时,Vue 将遍历这个对象的所有属性,然后通过 Object.defineProperty (vue 2.x)或者 Proxy (vue 3.x)定义属性的 gettersetter ,从而让 Vue 能够追踪当这些属性访问与修改。具体是怎么追踪的呢?每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把接触过的数据记录为依赖,这个过程也称为依赖收集,然后当依赖的 setter 触发时,就会通知 watcher ,从而使他们关联的组件重新渲染。

在这里插入图片描述

【Q4】你知道 Vue 双向数据绑定的原理吗?

Vue 双向数据绑定是指:数据变化更新视图,视图变化更新数据,例如输入框输入内容变化时,data 中对应的数据同步变化,data 中绑定的数据变化时,输入框的内容同步变化。

Vue 主要通过4个部分来实现双向数据绑定:

  • 监听器 Observer :对数据对象进行遍历,利用 Object.defineProperty() 在属性上都加上 gettersetter ,从而监听数据的变化。
  • 解析器 Compile :解析模板指令,将模板中的变量都替换成数据,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变化就会调用更新函数进行更新。
  • 订阅者 Watcher :订阅者是监听器和解析器之间通信的桥梁,主要任务是订阅监听器中的属性值变化的消息,当收到属性值变化的消息时,触发解析器中对应的更新函数。
  • 订阅器 Dep :订阅器采用发布-订阅设计模式,用来收集订阅者 Watcher 对监听器 Observer 和 订阅者 Watcher 进行统一管理。

【Q5】为什么 Vue 要采用异步渲染?异步渲染是如何实现的?

如果不采用异步渲染,那么每次更新数据都会进行重新渲染,这会对性能大打折扣,异步渲染是提高性能的手段之一。

只要监听到数据变化,Vue 将开启一个队列,并缓冲在同一个事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。然后,在下一个事件循环中,Vue 刷新队列并执行实际工作。Vue 内部对异步队列常使用原生的 Promise.thenMutationObserversetImmediate。如果环境不支持,则采用 setTimeout(fun,0)

【Q6】Vue 是如何检测数组的变化

Vue 官方中,提供了7个操作数组的方法:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

用于 “响应式” 的操作数组,也就是说,通过以上7个方法改变数组的元素,这会导致 data 中的数据变化,从而导致视图发生变化。除此以外,还可以通过 “新数组” 替换 “旧数组” 的方式来触发视图层的改变。但是,千万不能通过索引直接改变一个数组,这样不会引起视图层的改变,只是单纯的改变了数据。还有,不能通过修改数组长度来删除元素。

Vuedata 中的数组进行了原型链重写,指向了自己所定义的数组原型方法(也就是说上面的7个方法是Vue重写过的),从而实现了通过这些方法改变数组就可以通知视图层更新的效果。

【Q7】谈谈你对 Vue 生命周期的理解

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载DOM、渲染、更新、卸载等一些列过程,就是生命周期。

生命周期可大致分为 8 个阶段:实例创建前/后,挂载前/后,更新前/后,销毁前/后,分别对应8个回调钩子。

  • 实例创建前。beforeCreate() —— vue 实例的挂载元素 $el 和数据对象 data 都是 undefined ,还未进行初始化。
  • 实例创建后。created() —— 完成了 data 数据初始化,但未挂载。
  • 挂载前。beforeMount —— vue 实例的 $eldata 都初始化了,相关的 render 函数首次被调用。实例已完成以下配置:编译模板,把 data 里面的数据和模板生成 html。但是此时没有挂载到 html 元素上!!!
  • 挂载后。mounted —— el$el 替换,并挂载到 html 元素上。
  • 更新前。beforeUpdate —— 在数据更新之前调用。
  • 更新后。updated —— 此时组件 DOM 已经更新,所以可以执行依赖于 DOM 的操作。
  • 销毁前。beforeDestroy —— 实例销毁前调用
  • 销毁后。destroyed —— 实例销毁后调用。

【Q8】v-showv-if 有什么区别

两者都用于控制 “显示/隐藏” 元素,v-if 是真正的条件渲染,如果条件为假,则该元素不会被挂载到 DOM 树上,只有当条件为真时才进行渲染。v-show 本质是控制 cssdisplay 属性来进行显示隐藏的,不管初始条件是什么,该元素都会被渲染。

【Q9】 Vue 是单向数据流还是双向的?

官方是这样来介绍的:所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定,父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这也说明了不能在子组件中改变 propprop 永远都是只读的。如果非得改变 prop 的话,可以考虑在子组件中通过计算属性来修改。

每次父组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。

【Q10】组件通信的方式你知道哪些?

【方式一:props/$emit】

【父组件向子组件通信】
父组件直接通过标签属性的形式将数据传递给子组件,子组件通过实例的 props 属性即可获取到父组件传递过来的数据。

【子组件向父组件通信】
在子组件中,通过实例方法 this.$emit() 向父组件发送信息,将自己的数据传递给父组件。

该方法接收两个参数,第一个是事件名,第二个是携带的数据。

【方式二:provide/inject】

父组件使用 provide 向下提供数据,其下所有子组件都可以通过 inject 注入,不管中间隔了多少代,都可以注入多个来自不同父级提供的数据。

providevue 实例的配置选项,它是一个对象或者一个返回对象的函数。

inject 是一个字符串数组,或一个对象。

【方式三:$parent

$parent 可以从一个子组件访问父组件的实例。它是实例的属性,可以通过实例直接访问。

【方式四:$refs

通过 ref 标签属性可以标记一个子组件,然后通过实例的 $refs 来访问具体的子组件实例。

【方式五:vuex

通过 vuex 进行状态的统一管理。

未完,一直更

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章