面试题-Vue3

174 阅读3分钟

一、Vue3 核心概念

  1. Vue3 与 Vue2 的主要区别是什么?

    • 响应式系统从 Object.defineProperty 改为 Proxy,支持更多数据类型(如 Map/Set)。
    • Composition API 的引入,替代 Options API 的代码组织方式。
    • 性能优化:更快的虚拟 DOM、Tree-shaking 支持、编译时优化(如静态节点提升)。
    • 新增内置组件:<Teleport><Suspense><Fragment>
    • 更好的 TypeScript 支持。
  2. Vue3 的响应式原理是什么?

    • 基于 Proxy 代理对象,拦截属性的读取(get)和修改(set)。
    • 通过 Reflect 操作原始对象,避免直接修改原数据。
    • 依赖收集:通过 track 函数跟踪依赖,trigger 函数触发更新。
    const reactive = (target) => {
      return new Proxy(target, {
        get(obj, key) {
          track(obj, key); // 收集依赖
          return Reflect.get(obj, key);
        },
        set(obj, key, value) {
          Reflect.set(obj, key, value);
          trigger(obj, key); // 触发更新
          return true;
        },
      });
    };
    

二、Composition API

  1. 为什么需要 Composition API?解决了什么问题?

    • 逻辑复用:Options API 中逻辑分散在 datamethods 等选项中,Composition API 允许按功能组织代码。
    • 更好的 TypeScript 支持:函数式 API 更易于类型推导。
    • 代码可维护性:复杂组件中相关逻辑可聚合为自定义 Hook(如 useFunction)。
  2. refreactive 的区别是什么?

    • ref:包装基本类型为响应式对象(通过 .value 访问),也可包装对象。
    • reactive:直接代理对象,嵌套属性自动响应式。
    • 使用场景
      • 基本类型用 ref,对象/数组用 reactive
      • 模板中直接使用 ref 时自动解包,无需 .value
    const count = ref(0); // { value: 0 }
    const state = reactive({ name: "Vue3" });
    
  3. 如何实现跨组件的逻辑复用?

    • 使用 自定义 Hook(如 useCounter)封装可复用的逻辑:
      // useCounter.js
      export function useCounter(initialValue = 0) {
        const count = ref(initialValue);
        const increment = () => count.value++;
        return { count, increment };
      }
      

三、性能优化

  1. Vue3 的编译时优化有哪些?

    • 静态节点提升(Hoist Static):将静态节点提取为常量,避免重复渲染。
    • Patch Flags:在虚拟 DOM 中标记动态节点类型(如 TEXTCLASS),减少 Diff 成本。
    • Tree-shaking:未使用的模块(如未导入的组件)不会打包到最终产物中。
  2. 如何优化大型 Vue3 应用的性能?

    • 组件懒加载:使用 defineAsyncComponent 或动态 import()
    • 列表性能优化:为 v-for 添加唯一的 key,避免使用 v-ifv-for 同时作用同一元素。
    • 状态管理优化:合理使用 shallowRefshallowReactive 避免深层响应式开销。
    • 使用 v-oncev-memo 缓存静态内容。

四、新特性与内置组件

  1. <Teleport> 的作用是什么?举例说明。

    • 将子组件渲染到 DOM 中的其他位置(如全局弹窗、通知)。
    • 示例:将模态框挂载到 body 下,避免父组件样式影响。
      <template>
        <button @click="showModal = true">打开弹窗</button>
        <Teleport to="body">
          <Modal v-if="showModal" @close="showModal = false" />
        </Teleport>
      </template>
      
  2. <Suspense> 的使用场景是什么?

    • 处理异步组件加载状态(如骨架屏),提供 #default#fallback 插槽。
    • 示例:
      <Suspense>
        <template #default>
          <AsyncComponent />
        </template>
        <template #fallback>
          <div>Loading...</div>
        </template>
      </Suspense>
      

五、生态系统与工具

  1. Pinia 和 Vuex 的区别是什么?为什么推荐 Pinia?

    • Pinia 是 Vue3 官方推荐的状态管理库,特点包括:
      • 更简洁的 API(无 mutations,直接修改 state)。
      • 完整的 TypeScript 支持。
      • 模块化设计,无需嵌套模块。
    • Vuex 仍可使用,但 Pinia 更适合 Composition API 风格。
  2. Vite 在 Vue3 中的作用是什么?

    • 基于原生 ES 模块的构建工具,提供极快的冷启动和热更新。
    • 支持按需编译,避免打包整个应用。
    • 与 Vue3 深度集成,默认支持 .vue 单文件组件。

六、自定义hook示例

  1. 如何用 Composition API 实现一个防抖搜索功能?

    import { ref, watch } from "vue";
    export function useDebouncedSearch(fn, delay = 300) {
      const searchTerm = ref("");
      let timeoutId;
      watch(searchTerm, (newVal) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => fn(newVal), delay);
      });
      return { searchTerm };
    }
    
  2. Vue3 中如何实现父子组件通信?

    • Props / Emits:父传子通过 props,子传父通过 emit
    • v-model 双向绑定:支持多个 v-model(如 v-model:title)。
    • Provide / Inject:跨层级传递数据。
    • Expose:子组件通过 defineExpose 暴露属性或方法。