前端面试宝典

1. Composition API vs Options API

优缺点+场景+选择

  • Options API
    优点:写法直观、分类清晰,适合小型项目/新手;
    缺点:逻辑分散(一个功能跨 data/methods/computed)、复用困难(mixin 有命名冲突/数据来源不透明)。
  • Composition API(setup)
    优点:逻辑聚合(一个功能代码放一起)、复用性强(自定义 hooks 无冲突)、类型友好(TS 完美支持)、适合大型复杂项目;
    缺点:学习成本略高,代码组织需要规范。
    选择原则:小型项目/快速开发用 Options;中大型项目/团队协作/复杂逻辑用 Composition。

2. 响应式原理(面试必考手写)

(1)ref vs reactive 区别+场景(高频简答题)

特性refreactive
支持数据基本类型(String/Number/Boolean)+ 对象引用类型(对象/数组)
使用方式脚本中需 .value,模板中自动解包直接使用,无需 .value
响应式原理底层用 Object.defineProperty 劫持 value底层用 Proxy 代理整个对象
限制不能直接赋值(会丢失响应式)

场景

  • 基本类型数据 → 必用 ref
  • 对象/数组复杂数据 → 必用 reactive
  • 函数返回值/解构数据 → 推荐 ref

(2)手写简版响应式系统(面试官最爱)

// 依赖收集器:存储 effect 函数
class Dep {
  constructor() {
    this.effects = new Set(); // 去重
  }
  // 收集依赖
  depend() {
    if (activeEffect) this.effects.add(activeEffect);
  }
  // 触发更新
  notify() {
    this.effects.forEach(effect => effect());
  }
}

let activeEffect = null;
// 监听函数
function watchEffect(effect) {
  activeEffect = effect;
  effect(); // 执行一次触发依赖收集
  activeEffect = null;
}

// --------------- 手写 reactive ---------------
const reactiveMap = new WeakMap(); // 缓存代理对象
function reactive(target) {
  // 非对象直接返回
  if (typeof target !== 'object' || target === null) return target;
  // 已代理直接返回
  if (reactiveMap.has(target)) return reactiveMap.get(target);

  const dep = new Dep();
  const proxy = new Proxy(target, {
    get(target, key) {
      const res = Reflect.get(target, key);
      dep.depend(); // 读取时收集依赖
      // 深层对象递归响应式
      return reactive(res);
    },
    set(target, key, value) {
      const res = Reflect.set(target, key, value);
      dep.notify(); // 修改时触发更新
      return res;
    }
  });

  reactiveMap.set(target, proxy);
  return proxy;
}

// --------------- 手写 ref ---------------
function ref(value) {
  const dep = new Dep();
  return {
    get value() {
      dep.depend();
      return reactive(value);
    },
    set value(newVal) {
      value = newVal;
      dep.notify();
    }
  };
}

// 测试用例
const obj = reactive({ name: 'Vue3' });
watchEffect(() => console.log(obj.name));
obj.name = 'Vue3+Proxy'; // 自动打印更新

(3)watch vs computed 原理

  • computed惰性计算,依赖不变时缓存结果,依赖变化才重新计算;
  • watch监听指定数据,数据变化时执行回调,支持异步/立即执行。

3. Vue3 新特性(高频问答)

  • Teleport:将组件渲染到 DOM 其他节点(如弹窗挂载到 body);
  • Fragment:支持多根节点,无需外层包裹 div;
  • Suspense:异步组件加载中展示兜底 UI(实验性→稳定);
  • 自定义渲染器:跨平台(小程序/桌面端)核心,可自定义渲染 DOM。

4. Vue3 编译时+运行时优化

编译时优化

  1. PatchFlag:只更新动态绑定的内容,跳过静态节点;
  2. hoistStatic:静态节点提升,只创建一次;
  3. cacheHandler:缓存事件处理函数,避免重复创建。
    运行时优化
  4. Proxy 替代 Object.defineProperty,支持新增/删除属性、数组索引/长度监听;
  5. 按需编译,体积更小;
  6. 更好的 TS 类型推导。