自己面试前准备的VUE题目(加油~)

283 阅读10分钟

一. Vue3与Vue2 diff算法对比

总结:Vue 3 的 diff 算法通过静态树提升、Fragment 支持、Patch Flag、事件处理函数缓存和 Block Tree 等优化,显著提升了性能,减少了不必要的 DOM 操作。

Vue 3 和 Vue 2 的 diff 算法在核心思想上相似,都基于虚拟 DOM 和双端比较,但 Vue 3 在性能和细节上做了优化。以下是主要区别:

1. 静态树提升

  • Vue 2:每次重新渲染时,所有节点都会进行比较,包括静态节点。
  • Vue 3:通过静态树提升,标记静态节点并在后续渲染中复用,减少不必要的比较。

2. Fragment 支持

  • Vue 2:每个组件必须有一个根节点,多个根节点需包裹在一个父节点中。
  • Vue 3:支持 Fragment,允许组件有多个根节点,减少了不必要的包装元素。

3. Patch Flag

  • Vue 2:每次更新时,所有节点属性都会进行比较。
  • Vue 3:引入 Patch Flag,标记动态绑定的属性,更新时只比较这些属性,提升性能。

4. 缓存事件处理函数

  • Vue 2:每次重新渲染时,事件处理函数会重新生成。
  • Vue 3:缓存事件处理函数,避免重复生成,减少不必要的更新。

二. Vue 3 和 Vue 2 的主要区别是什么?

  • 答案要点

    • 性能优化:Vue 3 通过 Proxy 替代 Object.defineProperty 实现响应式,性能更好。
    • Composition API:Vue 3 引入了 Composition API,提供了更灵活的代码组织方式。
    • Tree-shaking 支持:Vue 3 的模块化设计支持 Tree-shaking,减少打包体积。
    • Fragment 支持:Vue 3 支持多根节点组件。
    • Teleport 组件:Vue 3 新增 <teleport> 组件,用于将内容渲染到 DOM 的其他位置。
    • 静态树提升:Vue 3 优化了虚拟 DOM 的 diff 算法,提升了渲染性能。

三. Vue 3 的响应式原理是什么?

  • 答案要点

    • Vue 3 使用 Proxy 实现响应式,而 Vue 2 使用 Object.defineProperty
    • Proxy 可以直接监听对象和数组的变化,无需递归遍历对象属性。
    • Proxy 支持监听动态添加的属性,而 Object.defineProperty 需要显式调用 Vue.set

四. Composition API 是什么?它解决了什么问题?

  • 答案要点

    • Composition API 是 Vue 3 引入的一种新的代码组织方式,核心是 setup 函数。

    • 解决的问题

      • 在 Vue 2 中,Options API 会导致逻辑分散在 datamethodscomputed 等选项中,难以维护。
      • Composition API 允许将相关逻辑集中在一起,提升代码的可读性和可维护性。
    • 核心函数

      • ref:用于创建响应式数据。
      • reactive:用于创建响应式对象。
      • computed:用于创建计算属性。
      • watch:用于监听数据变化。

五. Vue 3 的 Teleport 组件有什么作用?

  • 答案要点

    • Teleport 组件用于将组件的内容渲染到 DOM 的其他位置。

    • 典型应用场景:模态框(Modal)、通知(Toast)等需要脱离当前组件层级的情况。

    • 示例:

      <teleport to="body">
        <div class="modal">这是一个模态框</div>
      </teleport>
      

六. Vue 3 的 Fragment 是什么?

  • 答案要点:(vue实例挂载的DOM元素)

    • Vue 3 支持多根节点组件,称为 Fragment。

    • 在 Vue 2 中,组件必须有一个根节点,而 Vue 3 允许组件有多个根节点。

    • 示例:

      <template>
        <div>节点 1</div>
        <div>节点 2</div>
      </template>
      

七. Vue 3 的 Tree-shaking 是什么?它有什么优势?

  • 答案要点

    • Tree-shaking 是一种通过静态分析移除未使用代码的优化技术。
    • Vue 3 的模块化设计支持 Tree-shaking,可以减少打包体积。
    • 优势:减少最终打包文件的体积,提升加载性能。

八. Vue 3 的 Suspense 组件有什么作用?

  • 答案要点

    • Suspense 组件用于处理异步组件的加载状态。

    • 可以在异步组件加载完成前显示一个 fallback 内容(如加载动画)。

    • 示例:

      <template>
        <Suspense>
          <template #default>
            <AsyncComponent />
          </template>
          <template #fallback>
            <div>Loading...</div>
          </template>
        </Suspense>
      </template>
      

九. Vue 3 的 v-model 和 Vue 2 有什么区别?

  • 答案要点

    • Vue 2 中,v-model 是 v-bind:value 和 v-on:input 的语法糖。

    • Vue 3 中,v-model 可以绑定多个值,并且默认使用 modelValue 和 update:modelValue

    • 示例:

      html

      复制

      <!-- Vue 2 -->
      <input v-model="message" />
      
      <!-- Vue 3 -->
      <input v-model="message" />
      <input v-model:title="pageTitle" />
      

十. Vue 3 的响应式 API 有哪些?

  • 答案要点

    • ref:用于创建基本类型的响应式数据。
    • reactive:用于创建对象的响应式数据。
    • computed:用于创建计算属性。
    • watch 和 watchEffect:用于监听数据变化。

十一. Vue 3 的性能优化有哪些?

  • 答案要点

    • 响应式系统优化:使用 Proxy 替代 Object.defineProperty
    • 虚拟 DOM 优化:引入 Patch Flag 和静态树提升。
    • Tree-shaking 支持:减少打包体积。
    • Composition API:提升代码组织和复用性。

十二. Vue 3 的全局 API 有哪些变化?

  • 答案要点

    • Vue 3 的全局 API 改为按需导入,例如:

      import { createApp, ref, reactive } from 'vue';
      
    • 移除了 Vue.extend 和 Vue.nextTick,改为 createApp 和 nextTick

十三. WebSocket | 背景 概念 原理 使用 优缺点及适用场景

  • 答案要点
    • 在 WebSocket 出现之前,为了实现推送技术,所用的技术都是轮询,轮询是指浏览器每隔一段时间向服务器发出 HTTP 请求,服务器再返回最新的数据给客户端
    • WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,它使得客户端和服务器之间的数据交换变得更加简单,只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输,本质上一种计算机网络应用层的协议,用来弥补 HTTP 协议在持久通信能力上的不足

十四 模块化-ES Module(ES6 Module)

  • 特点

    • 是 JavaScript 的官方模块化标准。
    • 支持静态分析,适合 Tree Shaking。
    • 使用 import 导入模块,export 导出模块。
  • 模块化的优势

  • 代码复用:模块可以被多次复用,减少重复代码。

  • 依赖管理:模块之间的依赖关系清晰,便于维护。

  • 作用域隔离:每个模块有自己的作用域,避免全局变量污染。

  • 静态分析:ES Module 支持静态分析,适合 Tree Shaking 优化。

十五 动态路由?

  • 要在路由配置里设置 meta 属性,扩展权限相关的字段,在路由导航守卫里通过判断这个权限标识,实现路由的动态增加和跳转
  • 根据用户登录的账号,返回用户角色
  • 前端再根据角色,跟路由表的 meta.role 进行匹配
  • 把匹配搭配的路由形成可访问的路由

十六 Vuex的响应式处理?

当触发事件的时候,会通过 dispatch 来访问 actions 中的方法,actions 中的 commit 会触发 mutations 中的方法从而修改state 里的值,通过 getter把数据更新到视图

十七 为什么在 vue3 项目开发中使用 v-for 需要指定 key 值?  

在 vue3 中,使用 v-for 渲染列表时需要为每个项指定唯一的 key 值。这是因为 vue3 使用了虚拟 DOM 技术,通过比较新旧虚拟节点来进行高效的重新渲染。指定 key 值可以帮助 vue3 更准确地追踪每个节点的变化,减少不必要的重新渲染,提高性能。

十八 在Vue 2中,如果你需要在对象未完全初始化完成之前向其添加属性,有几种方法可以实现。

  • 使用Vue的$set方法
  • 使用计算属性或方法返回新的对象或属性值

十九 原型链

1. 什么是原型链?

  • 原型链是 JavaScript 中实现继承的机制。每个对象都有一个 [[Prototype]] 属性,指向它的原型对象。当访问一个对象的属性或方法时,如果对象本身没有该属性或方法,JavaScript 会沿着原型链向上查找。

2. prototype 和 __proto__ 的区别是什么?

  • prototype 是函数特有的属性,指向原型对象。
  • __proto__ 是对象特有的属性,指向它的原型对象。

3. 如何实现继承?

  • 通过 Object.create 或 new 关键字实现原型链继承。

  • 示例:

    function Parent() {}
    function Child() {}
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
    

4. 如何判断一个对象是否在另一个对象的原型链上?

  • 使用 instanceof 或 Object.prototype.isPrototypeOf

  • 示例:

    console.log(child instanceof Parent); // true
    console.log(Parent.prototype.isPrototypeOf(child)); // true
    

5. 如何获取对象的原型?

  • 使用 Object.getPrototypeOf

  • 示例:

    const proto = Object.getPrototypeOf(obj);
    

6. 如何设置对象的原型?

  • 使用 Object.setPrototypeOf

  • 示例:

    Object.setPrototypeOf(child, Parent.prototype);
    

二十 nextTick原理

Vue 3 的 nextTick 是一个用于在下次 DOM 更新循环结束后执行延迟回调的工具。它的原理主要涉及 Vue 的响应式系统和异步更新机制。

1. 响应式系统

Vue 3 的响应式系统基于 Proxy,当数据变化时,Vue 会触发组件的重新渲染。然而,Vue 并不会立即更新 DOM,而是将这些更新任务放入一个队列中,等待合适的时机批量执行。

2. 异步更新队列

Vue 使用异步更新队列来优化性能。当数据变化时,Vue 会将需要更新的组件放入一个队列中,并在下一个事件循环中批量处理这些更新。这样可以避免频繁的 DOM 操作,提升性能。

3. nextTick 的实现

nextTick 的实现依赖于 JavaScript 的事件循环机制。Vue 会优先使用微任务(如 Promise)来执行回调,如果当前环境不支持微任务,则会降级使用宏任务(如 setTimeout)。

主要步骤:

  1. 收集回调:当调用 nextTick 时,Vue 会将传入的回调函数放入一个队列中。
  2. 调度执行:Vue 会尝试使用微任务(如 Promise.resolve().then())来调度这些回调的执行。如果微任务不可用,则使用宏任务(如 setTimeout)。
  3. 执行回调:在下一个事件循环中,Vue 会依次执行队列中的回调函数。

4. 代码示例

javascript

复制

import { nextTick } from 'vue';

nextTick(() => {
  console.log('DOM 更新完成');
});

5. 使用场景

  • DOM 更新后操作:当你需要在 Vue 更新 DOM 后执行某些操作时,可以使用 nextTick
  • 等待异步数据:当你需要等待异步数据加载完成后操作 DOM 时,可以使用 nextTick

6. 源码解析

Vue 3 的 nextTick 实现主要位于 core/src/scheduler.ts 文件中。核心逻辑如下:

typescript

复制

const callbacks: Function[] = [];
let pending = false;

function flushCallbacks() {
  pending = false;
  const copies = callbacks.slice(0);
  callbacks.length = 0;
  for (let i = 0; i < copies.length; i++) {
    copies[i]();
  }
}

let timerFunc;

if (typeof Promise !== 'undefined') {
  const p = Promise.resolve();
  timerFunc = () => {
    p.then(flushCallbacks);
  };
} else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0);
  };
}

export function nextTick(callback?: () => void): Promise<void> {
  return new Promise((resolve) => {
    callbacks.push(() => {
      if (callback) callback();
      resolve();
    });
    if (!pending) {
      pending = true;
      timerFunc();
    }
  });
}

总结

nextTick 是 Vue 3 中用于在 DOM 更新后执行回调的机制。它利用 JavaScript 的事件循环机制,优先使用微任务来调度回调的执行,确保在 DOM 更新完成后执行用户代码。理解 nextTick 的原理有助于更好地掌握 Vue 的响应式系统和异步更新机制。

二十一. 事件循环常见面试题

1. 什么是事件循环?

  • 事件循环是 JavaScript 处理异步任务的机制,通过不断检查调用栈和任务队列来决定任务的执行顺序。

2. 宏任务和微任务的区别是什么?

  • 宏任务包括 setTimeoutsetInterval 等,每次事件循环执行一个宏任务。
  • 微任务包括 PromiseMutationObserver 等,每次事件循环会清空所有微任务。
  • 微任务的优先级高于宏任务。

3. setTimeout(fn, 0) 和 Promise.resolve().then(fn) 的执行顺序是什么?

  • Promise.resolve().then(fn) 是微任务,优先于 setTimeout(fn, 0) 的宏任务执行。

4. 以下代码的输出顺序是什么?

javascript

复制

console.log('Start');

setTimeout(() => {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(() => {
  console.log('Promise');
});

console.log('End');
  • 输出顺序:

    复制

    Start
    End
    Promise
    setTimeout
    

5. 如何理解 JavaScript 的单线程模型?

  • JavaScript 是单线程的,一次只能执行一个任务。通过事件循环机制,它可以高效地处理异步任务,避免阻塞主线程。

6. async/await 和事件循环的关系是什么?

  • async/await 是基于 Promise 的语法糖,await 后面的代码相当于 Promise 的微任务。

7. 如何优化事件循环的性能?

  • 减少同步任务的执行时间。
  • 避免长时间运行的微任务阻塞主线程。
  • 使用 Web Workers 处理耗时任务。