Vue3 零基础每日笔记(087):Vue3 高频面试题(下)

一、前言

面试篇(下):组件通信全家桶、路由与 Pinia、以及手写题环节。手写题给可直接默写的最短正确版,都源自系列实现过的代码。

Q1:Vue3 组件通信方式全说出(025-030/034 篇)

简答(背这张表,按"关系"记):

关系 方式 出处
父 → 子 props 025
子 → 父 emit 026
父 ↔ 子 组件上的 v-model(modelValue) 027
祖先 → 后代(跨层) provide / inject 028
父 → 子(内容分发) slot / 作用域插槽 029
父 → 子(属性透传) $attrs 033
父拿子 ref + defineExpose 033
任意关系 Pinia 全局状态 053-058

加分展开:选型原则------层级浅用 props/emit;跨层共享用 provide/inject 或全局状态(053 篇的判断标准:"离开组件树还有意义吗");slot 是"结构由父决定、数据由子提供"的反转场景。

Q2:路由守卫的执行顺序?(049 篇)

简答:完整导航流程:

text 复制代码
导航触发
→ 全局 beforeEach
→ 路由独享 beforeEnter
→ 组件内 beforeRouteEnter / beforeRouteUpdate / beforeRouteLeave
→ 全局 resolve 的 beforeEach 完成后:beforeResolve
→ 导航确认 → afterEach
→ DOM 更新 → beforeRouteEnter 的 next 回调(拿到实例)

加分展开:登录拦截放全局 beforeEach(meta.requiresAuth);页面标题设置放 afterEach(导航确认后再改 document.title 才对);每个钩子"return false / return 路由地址"即可中断/重定向,不需要调 next(Vue Router 4 推荐 return 风格)。

Q3:params 和 query 的区别?(047 篇)

简答 :params 是路径的一部分(/user/1,需要路由配置 :id),刷新还在(路径就是它);query 是地址栏问号参数(?tab=2),不需要路由配置,刷新也还在。真正的坑:params 通过对象编程式传参且不在 path 里声明的写法在 Vue Router 4 已被移除。

加分展开:传"不能出现在 URL 的数据"(编辑表单的大对象)→ 用路由 state/历史 state 或 Pinia 暂存;props 解耦(:props="true")让组件收参数不依赖 $route------组件可测性更好。

Q4:keep-alive 原理与缓存策略?(030/073 篇)

简答 :keep-alive 是抽象组件,内部用 Map 缓存组件实例的 vnode,命中缓存直接复用(不重新走 created/mounted),配合 include/exclude/max 控制。被缓存组件切换时触发 activated/deactivated 而非销毁。

加分展开 :LRU 策略(max 满了淘汰最久未用的);典型坑:include 匹配组件 name;列表页缓存 + onActivated 脏标记刷新是标准组合拳。

Q5:Pinia 为什么取代 Vuex?(053 篇)

简答 :四个字------砍掉中间商:没有 mutation,action 直接改 state;TS 完整推导;天然多 store 模块化(不需要 modules 嵌套);DevTools 支持完整。Pinia 是 Vue3 官方推荐,Vuex 处于维护态。

加分展开:

  • $patch 合并多处修改为一次更新(055 篇)
  • storeToRefs 解构保响应式(055 篇)
  • 持久化插件解决刷新丢失(057 篇)
  • Setup Store 与组合式函数心智统一(058 篇 TS 全推导)

Q6:手写防抖 debounce(038/076 篇)

ts 复制代码
function debounce(fn: Function, delay = 500) {
  let timer: ReturnType<typeof setTimeout> | null = null
  return function (...args: any[]) {
    if (timer) clearTimeout(timer)          // 重新来过:取消上一次
    timer = setTimeout(() => {
      fn(...args)                           // 停手 delay 后才执行
      timer = null
    }, delay)
  }
}

加分展开:两个必问延伸------①立即执行版(首次触发先执行,用于按钮)加一个 leading 参数;②为什么 setTimeout 里的 this/args 要闭包保存(保证执行上下文和参数正确)。一句话场景收尾:搜索框输入。

Q7:手写节流 throttle(038/076 篇)

ts 复制代码
function throttle(fn: Function, interval = 200) {
  let last = 0
  return function (...args: any[]) {
    const now = Date.now()
    if (now - last >= interval) {           // 距上次执行够久才放行
      last = now
      fn(...args)
    }
  }
}

加分展开:时间戳版(本文)首尾完整但最后一次可能丢;定时器版最后一次必执行但首击延迟------两者结合是完整版。场景收尾:滚动监听、resize。

Q8:手写一个最简组合式函数 useToggle(036 篇)

ts 复制代码
import { ref } from 'vue'

function useToggle(initial = false) {
  const state = ref(initial)
  const toggle = (next?: boolean) => {
    state.value = next ?? !state.value      // 传参指定值,不传取反
  }
  return [state, toggle] as const           // ★ as const 保持元组类型
}

加分展开 :as const 是 TS 细节(解构后类型不被拉宽成 boolean | Function);this 题眼:组合式函数的通用规范------输入响应式参数、返回响应式结果,VueUse 全部如此(079 篇)。

Q9:手写按钮权限指令 v-permission(034/070 篇)

ts 复制代码
import type { Directive } from 'vue'

const vPermission: Directive<HTMLElement, string | string[]> = {
  mounted(el, binding) {
    const roles = useUserStore().info?.roles ?? []
    const need = Array.isArray(binding.value) ? binding.value : [binding.value]
    if (!need.some((r) => roles.includes(r))) {
      el.parentNode?.removeChild(el)        // 无权限直接移除
    }
  }
}

加分展开:为什么移除而不是 display:none(隐藏可被 F12 破解);运行时角色会变则改用 v-if 方法式;永远补一句"后端必须再校验"体现安全意识。

Q10:讲讲虚拟列表的实现思路(074 篇)

简答:只渲染可视区的几十条数据。三步:①容器内放一个"总高度占位元素"撑出真实滚动条;②监听 scroll,用 scrollTop ÷ 行高算出 startIndex;③可视区内容切片渲染并 translateY 到对应位置,上下加缓冲防露白。

加分延伸 :不定高方案 = 先估高渲染、IntersectionObserver/实测后纠正(DynamicScroller);大数据表格直接用 el-table-v2 虚拟化;性能本质是把 DOM 数量从 O(n) 降到 O(可视区)。

三、答题心法

text 复制代码
1. 先结论后展开:一句话定调 → 细节 → 场景/项目印证
2. 手写题先写"最短正确版",被追问再升级(立即执行版、定时器版、并发控制)
3. 所有答案都能落到自己的博客/项目------"我踩过这个坑"是最强加分项

四、今日小结

  • 组件通信背关系表 (8 种 + 选型原则);守卫顺序先全局后组件,return 风格
  • 手写四连:防抖(闭包+清除)、节流(时间戳)、useToggle(as const)、v-permission(移除而非隐藏)
  • 虚拟列表口诀:占位撑滚动、scrollTop 算起点、切片渲染加缓冲
  • 面试本质:把 88 篇踩过的坑讲给面试官听

下篇预告

最终章:88 篇完结复盘------从环境搭建到项目上线的完整技术地图,项目结构终稿、学习方法沉淀、进阶路线(Nuxt / 源码 / 全栈)一个不落。下一篇 088。

相关推荐
IT_陈寒2 小时前
Redis大key删除为什么会导致服务卡顿?我的线上事故复盘
前端·人工智能·后端
系统集成-鹰翔2 小时前
ERP图片改名后仍命中识别缓存:缓存键、十分钟到期与调用计数
javascript·经验分享·后端
用户2705077725243 小时前
MCP 最小 Server 实测:3 个 JSON-RPC 报错与修法
前端
用户499335025073 小时前
一人VIP账号多人共用:Web 代理里的会话共享怎么实现
前端
用户老李3 小时前
无线电自学教程 05:第一台收音机——从矿石机到 SDR
前端
IPIPD3 小时前
Node.js请求遇到503怎么重试?先解析Retry-After,再做有上限退避
前端
葡萄城技术团队3 小时前
dsh-spreadjs-editor 的集成链路:把 SpreadJS Designer 嵌进 Agent 工作台
前端
FlyWIHTSKY4 小时前
vue2和vue3有什么区别,用法上有哪些区别
前端·javascript·vue.js
码云之上4 小时前
10 颗一模一样的「Edit」:中后台 Web Agent 怎么找到对的那一行
前端·人工智能·浏览器
量化分析码农4 小时前
【Python量化多因子实战 04】因子暴露不是 alpha:市值与行业中性化实战
前端·后端