ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vue2面试高频考点全解析:从响应式原理到diff算法

Vue2面试高频考点全解析:从响应式原理到diff算法 又到一年面试季Vue2的八股文依然是前端候选人绕不开的一道坎。虽然Vue3已经成为主流但市面上大量存量项目、老系统的维护、以及部分面试官根深蒂固的考察习惯都让Vue2面试题在2023年的前端面试里依然占据着相当比重。我自己在帮团队做技术面试时也发现一个现象很多候选人简历上写着精通Vue2但一问到响应式原理、diff算法、组件通信的边界情况就答得零零碎碎缺乏体系。这篇文章不是我临时拼凑的面试题清单而是结合了我这几年做面试官、带新人、以及自己啃源码的实战经验把Vue2面试中最常被追问的高频考点整理成了一套完整的知识框架。里面包含核心原理的深度拆解、面试官追问时的真实意图、以及我踩过的坑和总结的答题思路。不管你是准备跳槽的候选人还是想系统梳理Vue2知识体系的开发者这篇文章都能直接拿去用。老规矩不只是给答案更会讲清楚为什么。1. 响应式原理Vue2八股里最硬的骨头1.1 Object.defineProperty 到底拦截了什么面试官问Vue2响应式原理几乎100%会从Object.defineProperty切入。但很多人只背了一句通过Object.defineProperty劫持数据这远远不够。你要能说清楚它劫持的是对象的属性而不是对象本身。let data { name: vue2 } Object.defineProperty(data, name, { enumerable: true, configurable: true, get() { console.log(访问 name 属性) return vue2 }, set(newVal) { console.log(设置 name 属性, newVal) } })当你在Vue实例的data中声明一个对象Vue会递归遍历它的每一个属性用Object.defineProperty把它们全部转为getter/setter。这就是响应式数据的底层来源。但这里有个关键认知只有被遍历到的、已经存在的属性才会成为响应式的。如果在初始化之后往对象上新增一个属性那这个属性是没有getter/setter的不会触发视图更新。这就是为什么Vue2提供了Vue.set/this.$set来手动处理新增属性。1.2 依赖收集与派发更新从Watcher到Dep的完整链路光有getter/setter还不够Vue还需要知道谁依赖了这个数据以及数据变化后应该通知谁。这套机制由Dep和Watcher配合完成。可以这样理解它们的分工DepDependency是每个响应式属性专属的订阅中心记录着哪些地方用到了这个属性。Watcher是订阅者组件渲染、computed、watch都会创建对应的Watcher实例。完整的链路是这样的组件渲染时会创建一个render Watcher并在执行渲染函数之前把当前Watcher设置为全局的Dep.target。渲染函数读取数据触发对应属性的getter。getter内部调用dep.depend()把当前Watcher收集进该属性的订阅列表。数据被修改时触发setter。setter内部调用dep.notify()遍历所有订阅该属性的Watcher通知它们调用update()。update()并不会立刻重新渲染而是把Watcher推入异步更新队列等本轮事件循环结束后统一执行。这就引出了nextTick。面试时如果能把这个链路讲清楚并且画一下Dep、Watcher、Observer三者的关系图基本就能在这一题上拿到不错的分数。1.3 数组的补丁方法是怎么实现的数组的响应式处理是Vue2里一个非常经典的考点。因为Object.defineProperty无法检测到arr[0] 1这种通过索引赋值的变化Vue干脆放弃了对索引的监听转而采用拦截数组原型方法的策略。具体做法是Vue把data中数组的原型对象替换成一个经过改良的arrayMethods对象这个对象继承自真正的Array.prototype然后对以下七个方法做了拦截const methodsToPatch [ push, pop, shift, unshift, splice, sort, reverse ]当这些方法被调用时Vue不仅能执行原方法还能额外触发一次依赖通知。并且对于push、unshift、splice新增的元素Vue还会对新元素重新做一遍响应式处理保证新增的数据也是可响应的。面试追问通常是那arr.length 2这种操作能触发更新吗答案是不能。因为这种操作既不是索引赋值也没有走拦截方法。这也是为什么很多项目里会约定修改数组一律用splice或者整体重新赋值。1.4 响应式数据的坑与经典追问围绕响应式原理有几个高频追问场景值得专门梳理。第一个场景是对象新增属性不更新。最典型的例子data() { return { user: { name: 张三 } } }, methods: { addAge() { this.user.age 18 // 页面不会更新 } }解决办法有两种用this.$set(this.user, age, 18)或者直接给整个user对象重新赋值this.user { ...this.user, age: 18 }。第二个场景是直接通过索引修改数组。我见过太多新人在这个坑里挣扎this.list[0] new value // 不触发更新正确的做法是this.$set(this.list, 0, new value)或者this.list.splice(0, 1, new value)。第三个场景是为什么Vue3要换成Proxy。这里比较好的回答思路是Object.defineProperty 只能劫持属性所以需要递归遍历对象越深性能越差新增/删除属性检测不到数组的很多操作方式检测不到。而Proxy可以直接代理整个对象天然支持新增、删除属性的监听也支持对数组的深度拦截且惰性代理访问到才递归性能更好。提示面试官如果问到这里基本已经认同你对Vue2响应式有深度理解了。不要只背结论最好能把getter/setter、Dep、Watcher之间的联动过程用自己的话讲一遍。2. 虚拟DOM与diff算法能画出图才算过关2.1 虚拟DOM为什么存在很多人提到虚拟DOM第一反应是为了性能。这个说法不够准确。虚拟DOM真正的价值在于用JS对象来描述DOM结构把真实DOM的操作抽象成对象树的对比从而把频繁的DOM操作集中打包减少重排和重绘。打个比方真实DOM操作就像每次搬家都要重新装修整间屋子而虚拟DOM是先用图纸模拟一遍摆放方案确认最优布局后再一次性施工。它不一定比手写操作DOM更快但它的优势在于跨平台一份虚拟DOM可以渲染到浏览器、小程序、原生App等不同环境。可测试不依赖浏览器环境Node环境里也能跑。声明式开发者只需要描述数据是什么样DOM会把数据变成什么样交给框架处理。2.2 diff算法同层比较的核心逻辑Vue2的diff算法核心是同层比较不会跨层级比较。这是它的面试考点也是它的设计取舍。当新旧两个虚拟DOM树需要对比时Vue会从根节点开始逐层比较如果发现某个节点在旧树中有、新树中没有了会直接销毁整棵子树不会尝试去对比子树内部的差异。在同层节点对比上Vue2的diff流程大致是判断新旧节点是否sameVnode相同节点核心判断条件是key是否相同以及tag标签名和isComment等属性。如果不是相同节点直接替换。如果是相同节点则递归对比子节点。在子节点对比时Vue2采用了一种头尾双指针的优化策略。它会尝试四种情况的比较旧的头节点 vs 新的头节点旧的尾节点 vs 新的尾节点旧的头节点 vs 新的尾节点旧的尾节点 vs 新的头节点四轮比较中只要有一轮命中就复用节点、移动位置如果四轮都没命中再根据key从旧节点中查找可复用的节点。这样可以有效减少创建和销毁DOM的操作也是key值有意义的关键所在。2.3 key值在diff里的真实作用关于key最常见的解释是给每个节点一个唯一标识帮助diff更高效。这个方向是对的但不完整。key真正的价值在于让Vue可以准确地判断两个节点是否是同一个节点从而决定复用还是重建。同样一个列表div v-foritem in list :keyitem.id{{ item.name }}/div如果使用index作为key当列表中间插入一项时后面的所有项key都会变化导致Vue认为这些节点都变了从而执行全量更新。而用唯一id作为key时Vue可以精确定位哪些节点是新增、哪些节点是删减哪些节点可以复用性能差距在大型列表上会非常明显。面试时如果面试官追问什么场景下用index作为key会出问题你可以说除了性能之外还有状态保留的问题。比如列表项中包含输入框或勾选状态时使用内部可变的id作为key能保证组件实例被正确复用但如果用index增删元素可能会让已有组件的状态错乱。2.4 高难度追问为什么不直接操作真实DOM这个问题一般出现在对方确认你确实理解diff算法之后用来区分背过题和真正理解。比较好的回答思路是真实DOM操作的性能瓶颈不在于操作这一秒而在于操作之后浏览器要做的布局计算、样式计算、绘制、合成这一整套流程非常昂贵。如果每次数据变化都立刻操作一次DOM浏览器可能在极短时间内触发多次重排重绘造成卡顿。而Vue的 diff 是在JS层面完成的JS运行速度快于DOM操作几个量级。diff计算出最小变更集合后再批量执行真实DOM更新并且配合异步更新队列和nextTick把多次数据变化合并到一次修复中。这在复杂交互场景下能显著减少浏览器层面的性能损耗。3. 组件通信全家桶props、$emit、事件总线、provide/inject3.1 八种通信方式的适用场景组件通信是Vue2面试中覆盖面最广的考点。我整理了一张表标明了每种方式的适用场景面试前建议背熟通信方式适用场景特点与风险props / $emit父子组件通信最基础、最推荐单向数据流$refs / $children父访问子实例直接操作子组件耦合较高$parent / $root子访问父/根实例适合小型应急不推荐大范围使用provide / inject跨层级祖先与后代适合深层组件传值非响应式可配合computedeventBus$emit/$on非父子组件、兄弟组件需要手动清理避免内存泄漏Vuex全局共享状态适合复杂业务状态有明确规范$attrs / $listeners多层级透传props和事件适合二次封装组件v-model表单类组件双向绑定本质是props $emit的语法糖3.2 v-model的本质props $emit的语法糖很多候选人知道v-model能用于表单元素但一被问到自定义组件上怎么用v-model就卡住了。其实理解它的本质只需要看编译结果。在组件上使用custom-input v-modelvalue /等价于custom-input :valuevalue inputvalue $event /所以自定义组件要实现v-model需要在组件内部接收名为value的prop并在需要更新时触发this.$emit(input, newVal)。我面试时经常把这个题改成如果要支持v-model.trim或指定不同的prop名怎么做。用Vue2的model选项就能解决model: { prop: selected, event: change }这会让v-modelfoo编译成:selectedfoo changefoo $event。这个知识点在封装业务组件时非常实用。3.3 事件总线的内存泄漏问题eventBus在Vue2时代是很流行的兄弟组件通信方案但它有一个很多人忽略的大坑如果组件销毁时没有解绑监听事件监听函数会一直留在内存里造成泄漏。// 组件A 中监听 created() { bus.$on(refresh, this.handleRefresh) }, beforeDestroy() { bus.$off(refresh, this.handleRefresh) }面试时如果提到事件总线最好主动补一句必须在beforeDestroy里解绑或者直接用$once注册一次性监听这会让面试官觉得你踩过坑有工程意识。我的建议是新项目能不用eventBus就不用跨组件通信优先考虑Vuex或provide/inject因为状态流向更清晰不容易出现这个事件是哪来的这种排查难题。3.4 边界用例多层级嵌套通信怎么搞公司业务里经常遇到祖父组件要传值给孙子组件或者深层组件要触发最外层组件的方法。此时如果一层一层传props和$emit代码会非常啰嗦。provide / inject就是个很舒服的解法// 祖组件 provide() { return { theme: dark, changeTheme: this.changeTheme } } // 孙组件 inject: [theme, changeTheme]注意Vue2里provide / inject本身不是响应式的。如果想让注入的值响应当前数据变化可以传入一个getter函数或者在Vue2.6之后提供一个响应式对象。比如provide() { return { appState: this.appState // this.appState 本身是响应式对象 } }这种方式在封装大型公共组件库、布局组件时尤其好用能大幅减少透传的繁琐代码。4. 生命周期与nextTick命令执行顺序的常考区域4.1 单个组件的生命周期时序Vue2生命周期有八个主要钩子beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。面试里常问的是每个阶段能做什么、不能做什么。以我自己的经验总结来说beforeCreate实例初始化之前data和methods都拿不到一般很少用。createddata已初始化可以访问数据和方法但DOM还没挂载。适合在这里请求首屏数据、初始化非DOM依赖的配置。beforeMount模板已经编译成渲染函数但还没挂载到页面。mountedDOM已挂载可以操作DOM、访问$refs、初始化需要DOM的第三方库。beforeUpdate数据发生变化但DOM还没更新适合在这里做更新前的状态读取。updatedDOM已更新注意不要在updated里直接改数据容易导致死循环。beforeDestroy实例销毁前适合清理定时器、解绑事件、销毁第三方库实例。destroyed实例已销毁所有指令解绑、监听器移除。4.2 父子组件的钩子执行顺序这道题考的是对挂载流程和更新流程的完整理解。面试官最爱问父子组件挂载时钩子执行顺序是什么正确答案是父组件beforeCreate父组件created父组件beforeMount子组件beforeCreate子组件created子组件beforeMount子组件mounted父组件mounted简单记忆方法是父组件先创建但因为子组件在父的模板里所以子组件要先完成挂载父组件才挂载结束。更新时的顺序类似父组件beforeUpdate子组件beforeUpdate子组件updated父组件updated销毁时则反过来父beforeDestroy→ 子beforeDestroy→ 子destroyed→ 父destroyed。4.3 nextTick的实现机制nextTick的原理可以从为什么需要它讲起。当你在Vue中修改数据后DOM并不会立刻更新因为Vue会把本次数据更新推入异步队列等同一事件循环内的所有数据变化都处理完再统一更新DOM。nextTick就是让你在DOM更新完成后执行回调的工具。this.message hello this.$nextTick(() { console.log(this.$el.textContent) // 此时DOM已更新 })深入一点Vue2的nextTick会优先使用Promise.then微任务如果当前环境不支持Promise再降级为MutationObserver、setImmediate、setTimeout这样的宏任务。所谓的异步更新队列就是靠这个能力实现的。4.4 高频追问数据改变了DOM什么时候更新这个追问其实是把nextTick和响应式原理串联起来。你可以这样回答数据修改后setter触发依赖通知Watcher被推入异步队列。Vue会在当前事件的宏任务结束时统一执行队列中所有Watcher的更新然后触发重新渲染。在渲染完成后nextTick中的回调才会执行。所以如果你在修改数据后立即读取DOM拿到的还是旧值。我面试时还会追问一个场景在created里调用this.$nextTick回调能拿到DOM吗答案是能但要注意此时组件的mounted也没执行DOM虽然已经生成了但只是初次创建完毕如果依赖的是子组件渲染后的结果还需要等子组件也挂载完成。5. 计算属性 vs 侦听器面试官最爱考的选择题5.1 计算属性的缓存是怎么做到的计算属性computed被问到最多的就是缓存。它的底层实现其实依赖响应式系统中的Watcher。Vue会给每个计算属性创建一个computed Watcher它有两个关键状态dirty和value。首次访问计算属性时dirty为true会执行getter函数计算并缓存结果到value再把dirty置为false。之后访问同样的计算属性时因为dirty为false直接返回缓存的value不再执行getter。当计算属性依赖的响应式数据发生变化时computed Watcher收到更新通知把dirty重新置为true但不会立即重新计算。只有等到下次访问该计算属性时dirty为true才重新执行getter计算新值。这种懒计算设计让计算属性在性能上比方法更优秀。5.2 侦听器适合什么场景watch的适用场景和computed有明显区别。计算属性适合根据现有数据派生出新数据而侦听器适合当数据变化时执行某段异步操作或较重的逻辑比如搜索请求、路由切换、复杂校验等。watch: { keyword(newVal) { this.debouncedSearch(newVal) } }另外watch还支持deep: true深度监听和immediate: true立即执行这两个参数也是面试常考点。不过要注意深度监听会递归遍历对象比较消耗性能能用计算属性解决的就别用深度watch。5.3 手写计算属性的简化思路有些面试官不喜欢问你computed是什么而是让你实现一个简化版computed。这题考的其实是响应式原理的灵活运用。核心思路是创建一个computed Watcher在getter执行时收集依赖。维护一个dirty标记。当依赖数据更新时标记dirty true但不立即计算。当下次读取值时如果dirty为true重新执行getter否则返回缓存值。代码骨架大概是class ComputedRef { constructor(getter, dep) { this.getter getter this.dep dep this.dirty true this.value undefined } get value() { if (this.dirty) { this.value this.getter() this.dirty false } return this.value } update() { this.dirty true } }当然真正的Vue源码实现比这个复杂得多但只要能讲出dirty标记 缓存 依赖收集这个核心思路面试官对你的底层理解已经认可了。5.4 一道综合题搜索框防抖常见的业务场景是输入框里输入关键字实时请求后端接口。一般候选人会直接写一个watchsetTimeout防抖这没问题。但面试官往往加一句如果输入的同时还想显示一个经过处理的文本比如首字母大写你会怎么做正确思路是computed负责派生显示文本watch负责触发请求。一个是衍生值一个是副作用操作。分开处理代码会清晰很多。6. Vue2与Vue3的对比2023年绕不开的必考题6.1 响应式实现Object.defineProperty vs Proxy这组对比在2023年的面试里几乎是必问的。核心差异已经在响应式原理部分讲过了这里把关键点再浓缩一下Object.defineProperty只能劫持已有属性需要递归遍历Proxy可以直接代理整个对象支持新增、删除属性监听。对于数组Object.defineProperty无法监听索引变化必须打补丁方法Proxy天然支持数组的索引操作和length变化。性能上Proxy采用惰性代理访问到哪一层才代理哪一层Object.defineProperty初始化时就要递归所有对象数据层级深时性能开销大。Proxy的兼容性不如Object.defineProperty这也是Vue2还要维护的原因之一。6.2 API形态选项式 vs 组合式Vue3的Composition API组合式API和Vue2的Options API选项式API之间不只是写法不同更重要的是逻辑组织方式的变化。选项式API把同一功能的代码分散在data、methods、computed、watch各个选项中当组件功能复杂时阅读代码需要在不同区块之间反复跳跃。组合式API则允许你按照功能把相关代码聚合在一起类似按业务维度切分代码块。我见过很多初学者吐槽组合式API的ref/reactive/computed模板写法变复杂了但在真正的中大型项目中组合式API对可维护性的提升是实打实的——尤其配合setup里的自定义Hooks可以把可复用逻辑从组件里抽离得特别干净。6.3 性能优化静态标记与FragmentVue3在编译阶段做了很多优化其中最具代表性的是静态标记Patch Flags。Vue模板编译时会标记哪些节点是静态的、哪些节点动态绑定。更新时diff只需要处理带标记的动态节点大幅减少比较的节点数量这就是为什么Vue3在某些场景下比Vue2快很多。另外Vue3支持了Fragment多根节点模板最外层不再必须是一个单根元素。Vue2则要求组件模板必须有唯一根节点这一点在日常开发中也经常遇到。如果Vue2多根节点会直接编译报错Vue3则完全合法。6.4 面试官角度为什么还要学Vue2其实这是个很现实的问题。2023年还在面Vue2的公司基本是两类一类是存量项目以Vue2为主需要快速上手维护另一类是面试官想通过对比考察你对框架本质的理解深度。从候选人角度我的建议是不要只背Vue3新特性要把Vue2的原理吃透因为很多面试题是从Vue2切入再让你对比Vue3的。如果你能清楚说出Vue2的数组响应式靠补丁方法Vue3靠Proxy原生支持这种细节同时能解释两者演变的动机面试官会觉得你不是背题而是真的理解前端框架的发展脉络。7. 热搜里那些实战题签名、编辑器、WebView其实在考什么7.1 手写电子签名组件考的是事件绑定与Canvas热搜词里有一条很显眼vue2实现手写电子签名功能。这题在面试里属于实战题范畴属于高频出现的场景题。这道题的核心不是让你真的背一个签名组件而是考察你对Canvas绘图、事件绑定、以及组件封装的掌握。通常思路是在mounted里初始化Canvas上下文。监听mousedown、mousemove、mouseup事件在移动过程中通过canvas.lineTo画线。提供clear方法清空画布。提供getImageData或toDataURL方法导出签名图片。面试时如果时间充裕还可以主动提一句要注意Canvas的坐标适配使用getBoundingClientRect计算鼠标相对Canvas的位置避免画出来的线条偏移。这会让面试官觉得你有实际经验。7.2 封装wangeditor考的是v-model与props双向下钻另一个热搜是vue2使用wangeditor。这里面的考点其实是如何封装一个第三方富文本编辑器让它符合Vue2的组件规范。正确的封装模式是template div div refeditor/div /div /template script import E from wangeditor export default { name: WangEditor, props: { value: { type: String, default: } }, data() { return { editor: null } }, mounted() { this.editor new E(this.$refs.editor) this.editor.config.uploadImgServer this.uploadUrl this.editor.create() this.editor.txt.html(this.value) this.editor.config.onchange (html) { this.$emit(input, html) } }, beforeDestroy() { this.editor.destroy() } } /script这里面有几个容易踩坑的点必须在mounted之后初始化编辑器因为此时DOM已挂载。v-model的更新方向需要通过onchange触发input事件。编辑器实例要在组件销毁前调用destroy()防止内存泄漏。如果要监听外部的value变化更新编辑器内容需要加一个watch并判断当前值和编辑器内容不一致时才执行txt.html()。7.3 WebView加载Vue2页面考的是跨端通信热搜词里有一条微信小程序原生中webview 加载vue2 调用手机扫码优雅实现。这类问题的关键是跨端通信设计。微信小程序的web-view组件加载H5页面时H5页面不能直接调用小程序的扫码能力但通过wx.miniProgram.postMessage和wx.miniProgram.navigateBack这套桥接API可以实现双向通信。Vue2在其中的角色是管理H5页面的状态和交互逻辑并通过桥接层把扫码请求发给小程序端执行最终通过postMessage把扫码结果传回H5。面试时如果遇到类似的题重点展示你对桥接层设计的理解定义统一的通信协议比如postMessage({ type: SCAN_CODE, payload: {} })、封装独立的bridge.js模块、以及处理小程序和浏览器环境的差异用userAgent判断环境。这比纠结具体代码更能加分。7.4 uniapp中的支付弹窗考的是组件设计与条件编译还有个热搜是uniapp vue2实现底部微信、支付宝支付方式选择弹窗。这题本质上是组件设计与条件编译的组合题。弹窗组件需要考虑用v-model或visible属性控制显示/隐藏。支付方式列表通过props传入具备扩展性。底部弹窗的遮罩、滑动、关闭动画在App端和小程序端的表现可能不同需要通过条件编译分别处理。选中支付方式后通过$emit(select, method)通知父组件执行支付逻辑。能把这些结构设计点讲清楚说明你不仅会写页面还有组件抽象能力。8. 备战建议面试官到底想从八股里听出什么写到这里我想聊聊比题目本身更重要的事情。我做过不少技术面试发现很多候选人背题很熟练但一到追问就崩。原因在于他们把八股文当成标准答案在背而没有理解每道题背后的考察意图。举个例子面试官问Vue2的数据响应式原理是什么他其实不是想听你背诵Object.defineProperty的API文档而是想确认三件事你平时写的页面上数据更新时视图是怎么知道的。当数据更新遇到性能问题时你能不能从原理层面去排查优化。你在实际开发中碰到的变量改了没反应类问题能不能定位到深层次原因。所以我的建议是不要孤立地背题而是把每个面试题当成一条线索把它串联到你的实际项目中。比如你做过的项目里有没有遇到过数组更新视图不同步的问题你是怎样处理的这个项目经验配合理论原理效果远胜于单独的知识点背诵。另一条建议是准备几个迷你案例。比如手写一个响应式小Demo或者封装过一个编辑器组件。面试时用真实项目经历去佐证你对八股文的掌握比单纯说我理解原理更有说服力。8.1 三套高频追问链我总结了三套经常在面试里连环出现的追问链建议照着自测一下追问链Av-model的实现原理 → 自定义组件如何支持v-model→ 如果有多个值需要双向绑定怎么办用.sync修饰符或者model选项 →.sync和v-model的区别。追问链Bcomputed 为什么有缓存 → 缓存是怎么实现的 → watch 能不能实现同样效果 → 若讲究性能computed 和 watch 怎么选 → 能不能手写一个简化版computed。追问链C为什么$set能触发更新 →$set内部做了什么 → 数组为什么默认不做索引监听 → Vue3怎么解决这个问题 → 如果从Vue2迁移到Vue3哪些写法需要改。这三条链基本能把Vue2的核心八股串成一个知识网络。把每条链答通顺比单独背十个零散知识点有用得多。8.2 代码层面容易被忽略的规范最后再说一个容易被忽略的点很多面试题最终的落点其实是代码规范和工程习惯。比如不要在updated或watch里直接修改自己监听的数据容易死循环。组件销毁时一定要清理定时器、监听器、第三方实例。大型列表必须设置稳定的key不能图方便用index。v-for和v-if不要同时用在同一个元素上因为v-for的优先级更高v-if每次循环都会执行浪费性能。这些规范看似是经验之谈但面试官往往能从你主动提到这些细节中判断出你是有真实项目经验的人而不是纯粹刷题的面霸。Vue2的知识体系其实隐藏着很多前端框架设计的共性思维把它吃透之后再去看Vue3、React等框架很多概念都能触类旁通。如果你正在准备面试建议把这篇文章里的每个知识点结合自己项目中的实际场景用自己的话复述一遍。这种输出式学习比反复看别人的面经有效得多。
返回列表