资讯动态

VUE`````

发布时间:2026/10/17 16:42:35 来源:尧图企业网站定制
1 vue中组件的通信**1. props /emit∗∗父组件通过‘props‘向子组件传递数据子组件通过‘emit** 父组件通过 props 向子组件传递数据子组件通过 emit∗∗父组件通过‘props‘向子组件传递数据子组件通过‘emit 向父组件发送事件/数据。实现父子双向通信。2. ref父组件通过ref获取子组件实例。选项式 API 中通过this.$refs访问可直接调用子组件的方法或属性。3. v-slot父组件通过v-slot向子组件传入 DOM 节点、HTML 内容等。适合可复用组件、表格列值二次处理等场景。4. useAttrs()子组件通过useAttrs()一次获取父组件传递过来的所有属性未声明为props的那些如class、style、自定义属性等。5. provide / inject父组件通过provide提供变量子组件及后代组件通过inject注入变量。解决跨级组件祖孙通信问题。6. Vuex / Pinia通过全局 Store 存储和操作数据允许任意组件之间或页面之间共享状态。2 vue3中ref和reactive的区别1. 数据源类型ref可以包裹任意类型基本类型 对象/数组reactive只能包裹对象/数组不能用基本类型2. 访问方式ref需要通过.value访问和修改reactive直接访问不需要.value3. 解构响应性ref解构后仍保持响应式配合toRefs或结构本身是ref对象reactive解构后会失去响应式需要用toRefs包裹4. 底层原理ref通过Object包装 类 getter/setter 实现reactive通过Proxy代理整个对象实现5. 使用场景建议ref适合定义基本类型、需要解构或重新赋值的场景reactive适合定义复杂对象、不用解构且整体赋值的场景1. ref 可处理的数据类型可以处理基础数据类型如string、number、boolean也可以处理复杂数据类型如object、array2. reactive 可处理的数据类型仅能处理复杂数据类型object、array不允许传递基础类型的值3. 后端接口返回数据用 ref 还是 reactive推荐用ref。因为接口数据通常是对象但日后可能需要整体替换如res.data newDataref支持直接.value xxx而reactive整体赋值会丢失响应式4. 响应丢失的问题如何解决原因对reactive声明的对象进行解构或直接整体赋值方案1使用toRefs()将reactive对象解构为ref形式的响应式数据方案2改用ref声明避免解构带来的响应丢失方案3使用computed派生新数据5. 补充建议你的笔记未写但常用简单场景、基础类型、需要整体替换 → 用ref复杂嵌套对象且不需要整体替换、不需要解构 → 用reactive3 Vue中v-if和v-for的优先级在Vue 2和Vue 3中v-if和v-for的优先级是不同的。按你要求的12345列举形式整理如下1. Vue 2 中的优先级v-for优先级高于v-if意味着在同一个元素上同时使用时v-for会先执行循环每次循环时再判断v-if2. Vue 3 中的优先级v-if优先级高于v-for意味着在同一个元素上同时使用时v-if会先判断如果为false则v-for根本不会执行3. 为什么官方不建议一起使用无论 Vue 2 还是 Vue 3官方都不推荐在同一元素上同时使用v-if和v-for会造成性能问题Vue 2 中即使v-if为false也会先遍历列表会造成逻辑混乱Vue 2 和 Vue 3 行为不一致4. Vue 2 中的推荐写法想要过滤列表元素在外层包裹template v-for或使用computed计算属性先过滤再渲染想要控制是否渲染整个列表将v-if提升到父元素上5. Vue 3 中的推荐写法想要过滤列表元素必须使用computed计算属性先过滤因为v-if优先级更高无法实现条件性渲染循环中的某一项想要控制是否渲染整个列表将v-if提升到父元素上与 Vue 2 相同快速记忆口诀Vue 2先循环后判断Vue 3先判断后循环最佳实践永远不要放一起这是一份很全面的前端面试题清单。我已按你之前习惯的12345格式整理了每个问题的精简版核心答案。由于内容较多我会分成Vue篇、JS篇、项目场景篇三部分来回答。一、Vue 面试题1. Vue 响应式原理1.核心是数据劫持 发布订阅模式2.Vue2 使用Object.defineProperty递归遍历对象属性劫持 getter/setter3.Vue3 使用Proxy代理整个对象性能更好、支持数组和新增属性4.依赖收集getter 中收集依赖Watchersetter 中触发更新5.数组特殊处理Vue2 重写了push/pop/shift/unshift/splice/sort/reverse七个方法2. computed 和 watch 的区别1.computed是计算属性依赖于其他响应式数据有缓存机制依赖不变不重新计算2.watch是侦听器每当侦听的数据变化时执行回调无缓存3.computed 必须是同步的不能执行异步操作4.watch 可以执行异步操作支持deep和immediate选项5.使用场景computed 用于派生数据如全名、总价watch 用于执行副作用如请求接口、操作 DOM3. v-if 和 v-show 的区别1.v-if是条件渲染true 时创建 DOMfalse 时销毁 DOM2.v-show是条件显示始终存在 DOM通过 CSSdisplay: none切换3.v-if 有切换开销创建/销毁v-show 有初始渲染开销4.适用场景频繁切换用v-show运行时条件很少改变用v-if5.v-if 可与v-else-if、v-else配合使用4. 动态组件和异步组件的应用场景1.动态组件:is在同一个挂载点动态切换多个组件如 Tab 切换2.动态组件结合keep-alive可缓存组件状态3.异步组件按需加载打包时单独打包成 chunk首屏加载更快4.异步组件实现defineAsyncComponent(() import(./Foo.vue))5.异步组件适用场景体积大的组件、路由组件、非首屏可见的组件5. keep-alive 的作用和缓存实现1.作用缓存不活动的组件实例避免重复渲染和重复请求2.属性include白名单、exclude黑名单、max最大缓存数3.缓存原理内部维护一个cache对象key 为组件名和keys数组4.新增生命周期activated激活时调用、deactivated失活时调用5.缓存策略LRU最近最少使用达到 max 时删除最久未访问的缓存6. Vue 生命周期1.创建阶段setup组合式API→beforeCreate→created2.挂载阶段beforeMount→mountedDOM 已挂载可访问 $el3.更新阶段beforeUpdate→updated4.销毁阶段beforeUnmountVue3/beforeDestroyVue2→unmounted/destroyed5.keep-alive 专用activated/deactivated7. 组件通信你之前的笔记已详细总结这里简要列举1.props/$emit— 父子通信2.ref— 父调用子方法/属性3.provide/inject— 祖孙通信4.v-model— 父子双向绑定5.Vuex/Pinia/mitt— 全局/任意组件通信8. 具名插槽和作用域插槽的区别1.具名插槽给插槽命名实现多个插槽的区分用name属性2.作用域插槽子组件可以向插槽传递数据父组件通过v-slot:namescopeProps接收3.具名插槽写法template v-slot:header或template #header4.作用域插槽数据来源子组件通过slot :dataxxx传递5.应用场景具名插槽用于布局header/footer作用域插槽用于表格自定义列、列表自定义渲染9. mixins 和 extends 的区别1.mixins混入多个可复用的选项可混入多个2.extends继承单个组件只能继承一个3.合并策略组件自身 extends mixins后面的优先级高4.mixins 问题命名冲突、来源不清晰、维护困难Vue3 推荐用 Composition API 替代5.extends 适用场景创建基础组件多个组件继承相同配置10.attrs、attrs、attrs、listeners、$set 的作用1.$attrs接收父组件传递但子组件未声明为props的属性class/style 除外2.$listenersVue2接收父组件传递的原生事件和自定义事件Vue3 已合并到$attrs3.$setVue2向响应式对象添加新属性并触发更新。Vue3 的Proxy不需要4.$attrs常用于高阶组件透传 attribute 给内部子组件5.$attrs在组合式 API 中通过useAttrs()获取11. 常见的修饰符1.事件修饰符.stop、.prevent、.once、.self、.capture、.passive2.按键修饰符.enter、.tab、.delete、.esc、.space、.up、.down等3.v-model 修饰符.lazychange 事件触发、.number转数字、.trim去空格4.鼠标修饰符.left、.right、.middle5.系统修饰符.ctrl、.alt、.shift、.meta12. nextTick 的作用1.作用在下次 DOM 更新循环结束后执行回调获取更新后的 DOM2.原理Vue 异步更新队列 优雅降级Promise → MutationObserver → setImmediate → setTimeout3.使用场景修改数据后需要立即操作新 DOM4.Vue2 写法this.$nextTick()Vue3 写法import { nextTick } from vue5.源码核心将回调函数放入 callbacks 数组pending 标志控制只执行一次微任务/宏任务刷新13. 递归组件的实现与应用1.实现条件组件必须有name属性模板中通过name调用自身2.必须设置递归终止条件通常用v-if判断何时停止3.示例树形控件、多级菜单、评论回复列表4.性能注意确保数据层级有限避免无限递归5.配合provide/inject可实现子节点向父节点通信14. Vue 如何监听对象和数组的变化1.对象Vue2 用Object.defineProperty递归劫持所有属性Vue3 用Proxy2.新增/删除属性Vue2 无法监听需要$set/$deleteVue3 可直接添加3.数组Vue2 重写了 7 个变异方法push/pop/shift/unshift/splice/sort/reverse4.Vue2 数组问题通过索引修改arr[0] xxx无法触发更新length修改也无法触发5.Vue3 的 Proxy 可以直接监听索引赋值和 length 修改15. 路由守卫有哪些作用是什么1.全局守卫beforeEach、beforeResolve、afterEach登录校验、权限控制2.路由独享守卫beforeEnter单个路由配置内的守卫3.组件内守卫beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave4.beforeRouteEnter中不能访问this组件未创建可通过next(vm {})访问5.作用导航拦截、权限验证、页面标题设置、数据预加载、未保存提醒16. vue-router 路由模式有哪些1.hash 模式URL 带#基于hashchange事件兼容性好服务端无需配置2.history 模式URL 不带#基于pushState和popstate需服务端配置 fallback3.abstract 模式内存路由模式适用于非浏览器环境如 Node.js、小程序4.history 模式刷新会 404需要 Nginx 配置try_files $uri $uri/ /index.html5.设置模式createRouter({ history: createWebHashHistory() })17. 自定义指令如何实现1.全局注册app.directive(focus, { mounted(el) { el.focus() } })2.局部注册directives: { focus: { mounted(el) { el.focus() } } }3.钩子函数Vue3created、beforeMount、mounted、beforeUpdate、updated、beforeUnmount、unmounted4.常用场景权限按钮v-permission、防抖/节流、图片懒加载、点击复制5.可接收binding参数获取传值v-permission[admin]18. 虚拟 DOM 的优势和工作原理1.优势减少直接操作真实 DOM 的次数将 DOM 操作转为 JS 计算2.跨平台虚拟 DOM 是 JS 对象可以渲染到非浏览器环境Weex、小程序3.工作原理用 JS 对象描述 DOM 树 → 新旧虚拟 DOM 对比diff→ 计算出最小更新 → 批量更新真实 DOM4.diff 策略同层对比、不同 tag 直接替换、key 复用节点5.性能并非绝对更高初次渲染有额外开销优势在于频繁更新场景19. Vuex 和 Pinia 的区别1.Pinia 更轻量无 mutations只有 state/getters/actions2.TypeScript 支持Pinia 天然完美支持 TSVuex 需要额外配置3.模块化Pinia 自动按模块分包无需嵌套 modules4.DevTools 支持Pinia 完全兼容 Vue DevTools5.官方推荐Vue 3 新项目推荐 PiniaVue 2 老项目继续用 Vuex20. 如何实现 CSS 样式隔离1.scopedstyle scoped利用 PostCSS 给每个选择器添加唯一属性如data-v-xxx2.CSS Modulesstyle module通过$style.className使用生成哈希类名3.BEM 命名规范手动避免冲突如.block__element--modifier4.CSS-in-JS如 styled-components 在 Vue 中较少用5.深度选择器scoped 下需要穿透用:deep()Vue3或::v-deepVue221. 渲染函数的使用和场景1.定义使用h()函数创建 VNode替代模板语法2.场景1需要完全的编程控制模板不够灵活3.场景2动态生成大量重复结构减少模板代码4.场景3封装高阶组件动态渲染不同类型组件5.Vue3 写法import { h } from vuesetup() { return () h(div, ...) }22. defineAsyncComponent 函数作用1.作用在 Vue3 中定义异步组件实现按需加载2.基础用法const AsyncComp defineAsyncComponent(() import(./Comp.vue))3.高级配置loader、loadingComponent加载中组件、errorComponent错误组件、delay、timeout4.与 Vue2() import()的区别Vue3 统一用此 API支持更多配置5.适用场景首屏优化、路由组件懒加载、体积大的第三方组件23. Composition API 有哪些作用是什么1.ref基本类型响应式需要.value2.reactive对象响应式直接访问3.computed计算属性有缓存4.watch/watchEffect侦听数据变化。watchEffect自动收集依赖5.provide/inject依赖注入toRefs/toRef解构保留响应式生命周期钩子onMounted等24. toRefs 和 toRef 的用途1.toRefs将reactive对象所有属性转为ref用于解构时保留响应性2.toRef只转换单个属性为ref常用于处理可选值或 props3.toRef 的好处即使原属性不存在也会返回一个可用的 ref值为 null不会报错4.toRefs 丢失响应的情况只对第一层属性有效5.示例const { name, age } toRefs(person)→name.value可直接使用并保持响应二、JS 面试题1. 预编译1.JS 执行分两步预编译 → 执行2.函数预编译四部曲① 创建 AO 对象 → ② 找形参和变量声明 → ③ 形参实参统一 → ④ 找函数声明并赋值3.全局预编译创建 GO 对象即 window4.变量提升var声明提升到作用域顶部赋值留在原地5.函数提升整体提升优先级高于变量提升2. Event Loop 事件循环1.JS 是单线程依靠事件循环实现异步2.执行栈 → 微任务队列 → 宏任务队列 的顺序3.微任务Promise.then、MutationObserver、queueMicrotask4.宏任务setTimeout、setInterval、setImmediate、I/O、UI 渲染5.每次宏任务执行完后清空全部微任务再取下一个宏任务3. 区分数组和对象1.Array.isArray(arr)— 最推荐2.Object.prototype.toString.call(obj)— 万能方法返回[object Array]3.instanceof Array— 注意 iframe 跨上下文会失效4.arr.constructor Array— 原型链被修改可能不准5.Array.isArray兼容性IE9无法使用时可 polyfill4. 闭包及应用场景1.定义函数有权访问另一个函数作用域中的变量2.形成条件函数嵌套 内部函数被引用3.优点变量私有化、避免全局污染、记忆状态4.缺点内存泄漏变量常驻内存5.应用场景防抖节流、模块化封装、循环变量保存经典面试题5. this 指向问题1.默认绑定独立函数调用指向window严格模式undefined2.隐式绑定对象方法调用指向调用者3.显式绑定call/apply/bind指定this4.new 绑定构造函数this指向新创建的对象5.箭头函数没有自己的this继承外层作用域且无法用bind/call/apply修改6. 原型和原型链1.每个函数都有prototype属性显式原型2.每个对象都有__proto__属性隐式原型指向构造函数的prototype3.instanceof原理沿__proto__向上查找是否等于prototype4.原型链终点Object.prototype.__proto__ null5.属性查找先在自身找 → 原型链向上找 → 找不到返回undefined7. 数组去重腾讯1.Set[...new Set(arr)]— 最简单2.filter indexOfarr.filter((item, index) arr.indexOf(item) index)3.reduce includesarr.reduce((pre, cur) pre.includes(cur) ? pre : [...pre, cur], [])4.Map去重对象数组用JSON.stringify作为 key5.双重循环 — 最古老但兼容性最好8. 深浅拷贝实现1.浅拷贝Object.assign()、扩展运算符{...obj}、Array.slice()2.深拷贝简单版JSON.parse(JSON.stringify(obj))— 缺点函数/undefined/Symbol/循环引用会丢失3.递归实现遍历对象属性遇到对象/数组递归调用4.解决循环引用使用WeakMap缓存已拷贝的对象5.第三方库lodash.cloneDeep9. call、bind、apply 区别及手写 call1.call(this, arg1, arg2, ...)— 参数列表立即执行2.apply(this, [arg1, arg2, ...])— 参数数组立即执行3.bind(this, arg1, ...)— 返回新函数不立即执行柯里化4.共同点都可以改变函数内部的this指向5.手写 call 核心给目标对象临时添加函数属性执行后删除10. 隐式转换笔试题经典1.规则两端类型不同时尝试转换2.对象转基本类型先调用Symbol.toPrimitive→valueOf→toString3.[] ![]→true![]为false[]转布尔为true不同类比较转数字4.{} []→0{}被解析为代码块[]为05.经典题[] 0、[1] 1、[1,2] 1,2、null undefined等三、项目场景Token 无感刷新1. Token 无感刷新的业务场景1.场景用户登录后 token 过期在不提示重新登录的情况下静默刷新 token2.方案双 Tokenaccess_token 短时效、refresh_token 长时效3.流程access_token 过期 → 用 refresh_token 请求新 token → 重试原请求4.关键点用户完全无感知5.常见问题并发请求时重复刷新 token → 需要请求队列 防抖处理2. 长短 Token 的存储1.access_token内存vuex/pinia或 localStorage有效期短如 15 分钟2.refresh_tokenhttpOnly 的 cookie防 XSS或 localStorage有效期长如 7 天3.安全性refresh_token 建议不暴露给前端 JS用 cookie 且设置 httpOnly4.请求拦截器中自动添加 access_token5.响应拦截器中判断 401触发刷新逻辑3. 请求刷新 Token 接口的实现1.接口设计POST /refreshToken携带 refresh_token2.返回新的 access_token 和新的 refresh_token或滚动刷新3.后端需要验证 refresh_token 的有效性、是否被撤销4.支持 refresh_token 过期时前端清除登录状态跳转登录页5.刷新 token 的接口本身失败401时执行退出登录4. 无感刷新的最终实现1.维护isRefreshing标志位防止同时多次刷新2.维护failedQueue请求队列存储刷新期间等待的请求3.响应拦截器收到 401 → 判断是否为刷新接口 → 缓存请求 → 调用刷新4.刷新成功后 → 更新 token → 遍历队列重发请求 → 清空队列5.刷新失败 → 清空 token、状态 → 跳转登录页

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑