Vue面试题相关

Vue

Vuejs 响应式原理

Vuejs 响应式原理

参考资料

汪图南-个人博客-详细记录了 vue 及前端的一些资料

Vue 父子组件执行顺序

父子组件加载渲染过程(同步引入组件):
父 beforeCreate->父 created->父 beforeMount->子 beforeCreate->子 created->子 beforeMount->子 mounted->父 mounted

当异步引入子组件时,渲染顺序会有所变化:
父 beforeCreate->父 created->父 beforeMount->父 mounted->子 beforeCreate->子 created->子 beforeMount->子 mounted

子组件更新:
父 beforeUpdate->子 beforeUpdate->子 updated->父 updated

父组件更新过程:
父 beforeUpdate->父 updated

销毁:
父 beforeDestroy->子 beforeDestroy->子 destroyed->父 destroyed

Vue 的插件机制

如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

Vue.use 是一个全局方法,它是在initGlobalAPI通过调用initUse来注册这个全局方法的。initUse方法并不复杂:1.检测是否已经注册了插件 2.处理参数,将第一个参数之后的全部转数组。3.调用 install 方法

在 install 方法中,我们成功获取到了 Vue 构造函数以及我们传递的参数,在随后我们就可以做一些其它事情,例如:注册公共组件、注册指令、添加公共方法以及全局 Mixin 混入等等。

vue 源码分析-4-Vue.use()插件机制
Vue.use 插件机制

Vue 的四大生命周期和 8 个生命周期钩子函数

1、创建 2、挂载 3、更新 4、销毁

  1. beforeCreate vue 实例初始化之前调用
  2. created vue 实例初始化之后调用
  3. beforeMount 挂载到 DOM 树之前调用
  4. mounted 挂载到 DOM 树之后调用
  5. beforeUpdate 数据更新之前调用
  6. updated 数据更新之后调用
  7. beforeDestroy vue 实例销毁之前调用
  8. destroyed vue 实例销毁之后调用
    vue生命周期.png

Nuxt 的生命周期

Nuxt的生命周期.png
以上是 nuxt.js 的生命周期流程图,红框内的是 Nuxt 的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端

Vue 的八种通信方式

  1. props/$emit
  2. $children/$parent
  3. provide/reject provide 和 inject 不是响应式的,这点很重要,除非申明的属性是响应式的!
  4. ref
  5. eventbus
  6. Vuex
  7. localStorage/sessionStorage
  8. $attr/$listeners
    vue 中 8 种组件通信方式, 值得收藏!

watch methods computer 的区别和用法

computed 是计算属性的; 它会根据所依赖的数据动态显示新的计算结果, 该计算结果会被缓存起来。computed 的值在 getter 执行后是会被缓存的。如果所依赖的数据发生改变时候, 就会重新调用 getter 来计算最新的结果。computed 设计的初衷是为了使模板中的逻辑运算更简单, 比如在 Vue 模板中有很多复杂的数据计算的话, 我们可以把该计算逻辑放入到 computed 中去计算。
computer 和 method 的区别:1.computed 是基于响应性依赖来进行缓存的。只有在响应式依赖发生改变时它们才会重新求值, 也就是说, 当 msg 属性值没有发生改变时, 多次访问 reversedMsg 计算属性会立即返回之前缓存的计算结果, 而不会再次执行 computed 中的函数。但是 methods 方法中是每次调用, 都会执行函数的, methods 它不是响应式的。2.computed 中的成员可以只定义一个函数作为只读属性, 也可以定义成 get/set 变成可读写属性, 但是 methods 中的成员没有这样的。
watch 的使用场景是:当在 data 中的某个数据发生变化时, 我们需要做一些操作, 或者当需要在数据变化时执行异步或开销较大的操作时. 我们就可以使用 watch 来进行监听。

理解 Vue 中的 computed 用法
Vue 的 computed 和 watch 的细节全面分析
汪图南的博客也有详解

vue 的动态挂载组件和$el

extend $mount一般情况下用不到,特殊情况下的用处:1.单独开发 vue 组件 2.模板从服务端动态获取渲染 3.全局状态提示框等特殊组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue'

const AlertComponent = Vue.extend({
template: '<div>{{ message }}</div>',
data() {
return {
message: 'Hello, Aresn',
}
},
})

const component = new AlertComponent().$mount()
document.body.appendChild(component.$el)
// $mount 也有一些快捷的挂载方式,以下两种都是可以的
// 在 $mount 里写参数来指定挂载的节点
new AlertComponent().$mount('#app')
// 不用 $mount,直接在创建实例时指定 el 选项
new AlertComponent({ el: '#app' })

Vue 的虚拟 dom

Virtual DOM 其实就是一棵以 VNode 节点作为基础的树,用对象属性来描述节点,实际上它只是一层对真实 DOM 的抽象。最终可以通过一系列操作使这棵树映射到真实环境上。

为了避免不必要的 DOM 操作,虚拟 DOM 在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行 DOM 操作,从而避免操作其他无需改动的 DOM。
主要做了两件事:1.提供与真实 DOM 节点所对应的虚拟节点 vnode 2.将虚拟节点 vnode 和旧虚拟节点 oldVnode 进行对比,然后更新视图
优势:

  1. 具备跨平台的优势: 由于 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,所以使它具有了跨平台的能力,比如说浏览器平台、Weex、Node 等。
  2. 操作 DOM 慢,js 运行效率高我们可以将 DOM 对比操作放在 JS 层,提高效率: 因为 DOM 操作的执行速度远不如 Javascript 的运算速度快,因此,把大量的 DOM 操作搬运到 Javascript 中,运用 patching 算法来计算出真正需要更新的节点,最大限度地减少 DOM 操作,从而显著提高性能。
  3. 提升渲染性能: Virtual DOM 的优势不在于单次的操作,而是在大量、频繁的数据更新下,能够对视图进行合理、高效的更新

深入剖析:Vue 核心之虚拟 DOM
Vue-虚拟 DOM

Vue 的 diff 算法

Vue 的 diff 算法是基于 snabbdom 改造过来的,仅在同级的 vnode 间做 diff,递归地进行同级 vnode 的 diff,最终实现整个 DOM 树的更新。因为跨层级的操作是非常少的,忽略不计,这样时间复杂度就从 O(n3)变成 O(n)。

  1. 用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
  2. 当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
  3. 把所记录的差异应用到所构建的真正的 DOM 树上,视图就更新了
  • 用 JS 对象模拟 DOM 树 — element.js
  • 比较两棵虚拟 DOM 树的差异 — diff.js
  • 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树 — patch.js

Vuex

Vuex 原理

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

简述原理,emm
vuex 的核心是 store,store 基本是个容器,包含着整个应用程序的大部分状态。不能直接更改 store 中的状态,改变 store 中状态的唯一方法就是显式提交(commit) mutations。如果是异步的,就派发(dispatch)actions,其本质还是提交 mutations。

还要背诵 state、store、action、mutation 实现等。

请简述一下 vuex 实现原理
Vuex 源码解析
Vuex 状态管理的工作原理

Vue-Router

动态路由-权限管理

vue-router 里面有个方法addRoutes,可以用这个方法将额外的路由配置挂载在当前的实例上。不过此方法在 vue-router4.0 被弃用,建议使用addRoute方法来代替。

1
2
3
4
5
6
7
router.addRoutes([
{
path: '/new',
name: 'New',
component: () => import(/* webpackChunkName: "new" */ './views/New.vue'),
},
])
1
2
3
4
5
router.addRoute({
path: '/new',
name: 'New',
component: () => import(/* webpackChunkName: "new" */ './views/New.vue'),
})

推测是因为addRoutes没有带覆盖功能,同时 vue-router 并没有提供删除路由的方法,如果用此方法添加路由,重复的路由会报警告 ⚠️,需要手动处理还原一下  路由实例。
用此方法添加的代码分割的路由模块,加载是在路由到对应地址的时候才加载对应分割的 js 代码。
Vue-Router 文档
addRoutes 问题解决

Vue3

Vue 3 生命周期完整指南

Author: XavierShi
Link: https://blog.xaviershi.com/2021/10/21/Vue面试题相关/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.