Vue2高频面试核心:响应式原理、diff算法与Vue3对比

发布时间:2026/8/31 19:13:19

Vue2高频面试核心:响应式原理、diff算法与Vue3对比
2023年还在面试Vue2其实挺有意思的。一方面Vue3推了几年新项目基本都上Vue3了另一方面存量项目、老系统、各种后台管理模板Vue2的盘子依然非常大很多公司的面试题库里Vue2的内容也仍然占着不小的比重。更别提现在面试官喜欢追一句“你说说Vue2和Vue3的区别”如果你连Vue2的响应式原理都讲不清楚这个问题基本就挂在半空了。我自己在准备面试的时候把Vue2的高频题整理成了一份八股集合从响应式原理、生命周期、组件通信、diff算法到路由状态管理再到Vue2和Vue3的对比全部过了一遍。里面有不少题确实背起来很枯燥但反过来看这些题恰恰是把Vue2源码关键点串起来的线索。这篇博文把我整理的核心知识点和踩过的坑分享出来希望能帮你节约一点复习时间也能在面试现场多撑几个回合。1. 响应式原理最容易被追问到底的“八股之王”Vue2的响应式原理几乎是所有Vue2面试题里绕不开的题基本可以称为“八股之王”。我第一次准备时也觉得不就是Object.defineProperty嘛但面试官往往会一层一层往下问直到你答不上来为止。所以这部分不要只背结论得把整个链路想明白。1.1 Object.defineProperty与依赖收集的完整链路先回答最基础的问题Vue2是怎么做到数据变了视图自动更新的其实核心就两件事拦截数据的读写然后在读的时候收集依赖在写的时候触发更新。Vue2在初始化data时会通过new Observer()把data对象递归遍历一遍对每个属性调用Object.defineProperty重新定义getter和setter。getter里做的事情是依赖收集setter里做的是派发更新。依赖收集的关键是Dep和Watcher这两个类。我理解的时候画了一条链每个响应式属性都有一个Dep实例可以理解为一个“订阅者列表”。每个组件或者某个computed、watch都有一个Watcher实例代表这个“订阅者”。当组件渲染时会读取data里的数据触发gettergetter里调用dep.depend()把当前Watcher收集到Dep的subs数组里。当数据变化时setter触发dep.notify()把subs数组里的每个Watcher都执行一遍update()导致视图重新渲染。面试官在这个地方很喜欢追问为什么需要在getter里收集依赖而不是在初始化时直接把所有Watcher都绑上去因为Vue的依赖收集是“按需”的。比如你的模板里只用了name这个字段那么age字段的Dep里就不应该收集到这个组件的Watcher。如果一开始就全部绑定那任何数据变了所有组件都要重新渲染性能会非常差。Vue之所以能做到精准更新靠的就是getter触发的时机恰好是模板求值的时候。1.2 Vue2响应式的三大死穴新增属性、删除属性、数组索引这部分是面试中超高频的追问点。先说场景data() { return { user: { name: 张三 }, list: [a, b, c] } }然后你执行了this.user.age 18或者this.list[0] x会发生什么答案是视图不会更新。因为Object.defineProperty是在初始化时针对已有的属性做拦截的新增的age属性压根没有getter和setterVue根本感知不到。同理数组的索引修改this.list[0] x也无法触发更新。可能你听过Vue2对数组做了特殊处理但那个处理只覆盖了7个会修改原数组的方法push、pop、shift、unshift、splice、sort、reverse直接通过索引赋值是管不到的。那解决办法是什么八股答案就是Vue.set和this.$set。$set的实现原理其实也不复杂如果target是对象就调用defineReactive给这个新属性加上getter和setter然后手动触发一次依赖通知如果target是数组就调用重写过的splice方法利用数组方法拦截机制触发更新。数组索引无法监听到底层原因是Vue源码里对数组的响应式处理只重写了那7个方法并没有对数组的每个索引也做defineProperty。之所以这么设计是因为数组元素往往数量大、变化频繁如果全部拦截性能损耗太大。面试时如果能主动说出这一层面试官会认为你对源码是真正有理解的而不是只背了结论。1.3 面试官常问的降级方案与性能坑在实际项目中如果频繁往对象上新增属性或者根据后端返回的数据动态设置字段光靠$set其实很啰嗦。我面试时被问过“有什么更好的实践”我的回答是尽量在data里把对象结构声明完整预置好所有会出现的字段哪怕是空值。用Object.assign赋值时注意Object.assign会触发setter所以如果合并的对象里有新字段最好分开处理先$set新字段再批量赋值。数组尽量用splice、push等方法替换元素不要直接操作索引。如果数据量特别大或者嵌套层级特别深可以考虑直接在业务层做不可变数据更新换一个新的对象/数组整体赋值这样虽然会重新触发渲染但代码逻辑简单也避免了深层响应式的性能坑。还有一个性能问题值得提一下Vue2的响应式是递归遍历的如果你的data里某个字段非常庞大比如一个几千条数据的树形结构初始化时的递归defineProperty会消耗不少时间。面试官问到“Vue2的性能瓶颈有哪些”时这个点非常加分。注意很多人以为Object.freeze可以解决这个问题。实践中确实可以如果你有一块数据是纯展示的、完全不需要响应式可以在data里先Object.freeze再返回Vue的observer检测到对象是frozen的话会跳过defineProperty省下很大的初始化开销。这是我实测有效的方式在渲染超大表格时能明显感觉到初始化变快。2. computed、watch与data考得最频繁的“数据三板斧”Vue2面试题里computed和watch的区别可以说是选择题、简答题里出现频率最高的内容几乎每次面试都会碰到。这个问题看似简单但面试官经常会挖细节比如“computed为什么能缓存”“watch能拿到oldValue有什么原理”等等。2.1 computed的缓存机制与求值过程computed和methods最大的区别就是缓存。面试官问“computed为什么可以缓存”很多人的回答是“因为computed依赖的数据不变就不会重新计算”这个回答只能给个及格分。深入一点应该这样说computed内部是基于Watcher实现的但它的Watcher有两个特殊的标志lazy: true和dirty: true。当lazy为true时初始化时不会立即求值而是要等到真正读取computed的值时才去计算。计算完成后dirty会变成false表示这个值现在是“干净”的之后如果再读取这个computed就直接返回上次计算的结果不会再重新执行getter函数。那什么时候dirty会重新变成true呢就是它依赖的响应式数据发生变化时。当computed的依赖项被修改触发了dep.notify但因为它是一个lazy watcher不会立刻重新求值而是先把dirty置为true。下一次再访问这个computed时发现dirty为true才重新计算并把dirty置为false。这个机制就是缓存的核心。所以computed特别适合用在计算量较大或者被多次引用的场景比如购物车的总价、过滤后的列表。用computed还有一个格式问题值得注意计算属性默认只有getter但你也可以给它写settercomputed: { fullName: { get() { return this.firstName this.lastName }, set(val) { const names val.split( ) this.firstName names[0] this.lastName names[1] } } }这个写法在面试里也时不时出现尤其是考察vuex中mapGetters使用时对computed的配合场景。2.2 watch的适用场景与深度侦听watch适合的场景是当数据变化时需要执行异步操作或开销较大的操作比如搜索防抖、路由切换、接口重新请求。watch能拿到变化前后的值这在做“变化检测”类逻辑时非常有用watch: { keyword(newVal, oldVal) { console.log(从, oldVal, 变成, newVal) this.debouncedSearch(newVal) } }面试里常考的一个点是deep: true。为什么要deep因为和computed一样watch默认也是浅层次的只有监听的对象引用发生变化时才会触发。如果是this.obj.a 1这样修改嵌套属性默认watch是监听不到的。用deep确实能解决这个问题但代价也很大Vue会深度遍历这个对象的所有属性给每个属性都绑定监听。如果对象非常深且变化频繁性能损耗很明显。一个替代方案是直接监听具体路径watch: { obj.a: function(newVal, oldVal) { // 只监听obj的a属性 } }这种字符串路径的写法很实用在表单校验、联动逻辑里经常用到。2.3 data为什么是函数而不是对象这道题几乎是基础题里的必考。原因特别简单组件是要被复用的如果data是一个对象那么所有复用这个组件的地方会共享同一个data引用改了一个地方的数据另一个地方也跟着变这肯定不是我们要的效果。但如果data是函数每次创建组件实例时都会调用这个函数返回一个全新的数据对象这样每个组件实例都有自己独立的数据副本。有个小细节根实例的data可以是对象因为在new Vue()的时候只会存在一个根实例不存在复用问题。面试如果被问到把这个点也说出来能体现你思考过细节。3. 生命周期与nextTick几乎是面试开场必问生命周期这道题面试官可能从任何角度切入比如“created和mounted的区别”“父子组件生命周期顺序”“为什么不在created里操作DOM”“nextTick是什么”等等。这块的内容比较零散但也是必背的基础分。3.1 父子组件生命周期执行顺序我把这个顺序背下来之后面试时答题非常有底气父组件beforeCreate父组件created父组件beforeMount子组件beforeCreate子组件created子组件beforeMount子组件mounted父组件mounted更新阶段父组件beforeUpdate子组件beforeUpdate子组件updated父组件updated销毁阶段父组件beforeDestroy子组件beforeDestroy子组件destroyed父组件destroyed为什么是这个顺序因为父组件在beforeMount后开始渲染渲染过程中发现需要挂载子组件于是进入子组件的初始化流程等子组件完全挂载完成后父组件才能完成自己的挂载。所以子组件的mounted一定在父组件的mounted之前。更新阶段也一样父组件数据变了要重新渲染子组件先完成自己的更新父组件的更新才算完成。记住“子先父后”这个原则基本上整个顺序都不会记错。3.2 created和mounted到底该干什么created阶段data和props已经初始化完成methods、computed、watch都可以使用了但DOM还没有生成所以不能访问this.$el。这阶段适合做不依赖DOM的初始化操作比如调用接口获取列表数据并赋值给data等待页面渲染时直接显示设置跨组件事件总线监听器初始化一些非DOM依赖的第三方库比如纯JS的工具类从缓存/localStorage读取数据mounted阶段模板已经渲染完成DOM已经挂载到页面可以操作DOM了。这阶段适合做需要计算元素尺寸、位置的操作初始化依赖DOM的插件比如图表库、富文本编辑器、签名板等给DOM绑定原生事件或定时器一个很常见的坑是在created里调用接口拿数据然后想在created里操作刚渲染的DOM结果拿到的是undefined。因为即使接口数据是同步返回的DOM也还没渲染。还有一种情况mounted里拿到DOM去做测量但发现高度不对。这时候往往是因为有图片、字体、异步子组件还没加载完成导致的。解决办法就是配合nextTick或者直接在updated里做判断或者等图片的onload事件后再计算。3.3 nextTick的原理与面试考点nextTick这个考点我见过最多的问题是“你改了data之后为什么DOM没有立刻变化”因为Vue的DOM更新是异步的。当你修改data后Vue不会马上更新DOM而是会开启一个队列把同一事件循环内所有的数据变更都缓存起来用一个Promise.then或者微任务去统一执行更新。这样做的好处是避免重复渲染比如你在一个循环里给100个数据赋值Vue只需要渲染一次。nextTick的作用就是在这个DOM更新完成后再执行回调this.message hello this.$nextTick(() { console.log(this.$el.textContent) // 输出更新后的内容 })关于nextTick的实现Vue2源码里有一个降级策略优先使用Promise微任务如果不支持就用MutationObserver微任务再不行就用setImmediate宏任务最后降级到setTimeout。之所以要降级是为了兼容不同的浏览器环境。面试时会问的一个高级点为什么用微任务而不是宏任务。因为宏任务会在下一轮事件循环才执行延迟更大用户体验更差微任务在当前任务结束后立刻执行DOM更新能更早完成性能感知更顺滑。4. 组件通信十种方式必须烂熟于心组件通信的问题是Vue2面试的“重头戏”。从最简单的props到最冷门的$parent面试官都会考。这个部分我自己整理了一个通信方式清单基本上涵盖了所有题目。4.1 父子组件通信props、$emit、$refs、v-model父子通信是Vue最基础的通信方式父传子props父组件在子组件标签上绑定属性子组件通过props接收。子传父$emit子组件触发自定义事件父组件监听事件并处理。父访问子$refs父组件通过this.$refs.child调用子组件的方法或访问数据。v-model的语法糖本质上是props $emit的组合父组件传value属性子组件触发input事件。面试时喜欢让你手写一个v-model的自定义组件这个必须会template input :valuevalue input$emit(input, $event.target.value) /template script export default { name: MyInput, props: { value: String } } /script父组件这样用my-input v-modelmsg /这其实就是v-model的语法糖。如果要扩展比如定义自定义的model配置可以这样model: { prop: checked, event: change }这属于比较进阶的考题但2023年的面试里出现频率并不低。4.2 兄弟组件与跨级通信eventBus、provide/inject、$attrs/$listeners兄弟组件A要通知兄弟组件B数据变了常见的解法是事件总线eventBus新建一个空的Vue实例作为中央事件总线组件A通过bus.$emit(some-event, data)发射事件组件B通过在created里bus.$on(some-event, callback)监听事件。但eventBus有个明显的坑如果组件销毁了事件监听没有移除就会造成内存泄漏和重复触发。所以使用eventBus时必须在beforeDestroy里bus.$off掉自己注册的事件。provide/inject这个主要解决祖先组件和后辈组件之间的通信避免一层层传props。但它有一个特性inject的数据不是响应式的除非你provide的是一个响应式对象。所以使用时要谨慎适合传递“静态配置类”的数据比如主题、用户权限、api地址等。$attrs和$listeners在写通用组件时非常好用。$attrs会包含父组件传入的非props属性$listeners包含父组件注册的所有事件。当你在组件内部给某个子元素做属性透传时这两个非常方便。// 孙组件 mounted() { console.log(this.$attrs) // 拿到所有未声明为props的属性 console.log(this.$listeners) // 拿到所有监听事件 }4.3 状态管理工具Vuex到底解决了什么问题面试官问“为什么要用Vuex”时我的理解是当多个组件需要共享同一份状态或者不同路由页面之间需要同步数据时用props传值会非常繁琐和脆弱事件总线又不好维护。Vuex把状态集中到store里统一管理组件通过commit提交mutation、通过dispatch触发action从而实现可预测的数据流。Vuex的核心概念要记住state全局共享的数据getters相当于store的计算属性mutations修改state的唯一入口同步操作actions可以包含异步操作不直接改state而是通过commit提交mutationmodules模块化每个模块有自己的state、mutations、actions、getters配合namespace解决命名冲突面试里追问最多的就是“为什么mutation必须是同步的而action可以异步”。因为Vuex的devtools会记录每一次mutation的变更记录如果mutation里做了异步操作那你看到的变更记录前后状态就不对应了调试工具就失去了意义。action里做异步操作然后等结果回来后commit一个mutation这样每次状态变更都能被清晰地追踪到。5. 虚拟DOM与diff算法决定了你能谈多深虚拟DOM和diff算法几乎可以算Vue2面试题里的压轴题了。面试官问到这个层面往往是想了解你对框架底层理解深入程度。这个部分光背结论没用一定要能用自己的话讲清楚。5.1 虚拟DOM是什么为什么需要它虚拟DOM本质上就是一个描述真实DOM结构的JavaScript对象。比如{ tag: div, props: { id: app, class: container }, children: [ { tag: span, props: {}, children: [hello] } ] }这个对象就是所谓的VNode。渲染时Vue会通过render函数生成VNode树然后通过patch方法把VNode树映射成真实DOM。为什么需要虚拟DOM我觉得有两个核心原因第一模板编译后直接操作真实DOM的成本很高。浏览器对DOM的读写和修改是昂贵的频繁操作真实DOM会造成不必要的重排和重绘。通过对比虚拟DOM的diff可以在内存中计算出最小的更新范围再统一批量应用到真实DOM上。第二虚拟DOM让跨平台成为可能。Vue的runtime不仅可以在浏览器里跑还可以在微信小程序、原生应用等场景下渲染靠的就是同一套VNode描述结构在不同平台上走不同的渲染逻辑。React Native也是如此。5.2 面试必问的diff算法优化策略Vue2的diff算法做了四个优化策略记住这几个能让你在面试时讲得非常清晰同层比较新旧VNode树只在同一层级比较不会跨层比较。即使两个节点在结构上完全一样但层级不同也会被视为不同节点直接销毁重建。这个策略大大降低了算法复杂度从O(n^3)降到O(n)。首尾指针法在对比同一层的children时不是简单遍历而是定义了四个指针oldStartIdx、oldEndIdx、newStartIdx、newEndIdx。通过新旧两端指针逐个对比然后根据匹配情况移动指针。这个策略能快速处理最常见的“头插”“尾插”“移动”场景。key的作用如果给v-for项设置了唯一的keyVue就能通过key判断两个节点是否是同一个节点。即使位置移动了Vue也能复用这个组件实例而不是销毁重建。所以key必须稳定且唯一。组件复用与更新如果两个VNode的tag相同就认为它们是同一个节点走组件复用的逻辑只做属性更新和子节点更新不会销毁重建。追问最狠的一个问题是为什么不建议用index作为key因为如果列表顺序发生变化比如进行了一次头部插入那么使用index作为key的话所有元素的索引都会发生变化Vue通过key对比时会认为每个节点的位置都变了从而对每一项都执行一次更新操作甚至可能导致组件状态错乱。典型的问题是列表项里有checkbox用户在第一行勾选了然后删除了第一行结果第二行的checkbox被勾上了因为index的key对不上。所以key应该用唯一id比如数据的id值。这条在面试时跟vue列表渲染的具体场景一起讲很加分。5.3 patch流程的关键步骤简单理解patch的过程是这样的如果oldVNode不存在直接创建新节点挂载到容器上。如果newVNode不存在直接销毁旧节点。如果新旧节点不是同一节点tag不同或key不同直接销毁旧节点创建新节点。如果新旧节点是同一节点则对比它们的内容做patch更新更新propsclass、style、attrs、domProps等更新事件监听器递归对比children走diff逻辑整个流程的核心原则就是“能复用就复用不能复用才重建”。6. vue-router与路由守卫考察你的工程落地能力路由的问题在Vue2面试里主要考察你对vue-router的理解深度以及你在实际项目中怎么处理权限控制这类需求。6.1 hash模式与history模式的区别vue-router有两种模式hash模式URL里有#号比如http://localhost:8080/#/home。hash变化不会向服务器发送请求因此不需要服务器额外配置适合静态部署。缺点是URL不够美观有#号。history模式URL是正常的路径比如http://localhost:8080/home更美观。但history模式依赖浏览器的History API当用户直接访问某个深层路由时服务器必须配置所有路由都返回index.html否则刷新后会404。面试官问到“为什么history模式部署需要nginx配置try_files”时本质上也是这个原理因为静态服务器并不知道/home这个路径对应哪个文件所以需要统一回退到index.html让前端路由接管。6.2 路由守卫与登录权限的完整实现vue-router的守卫分为三类全局守卫beforeEach、beforeResolve、afterEach路由独享守卫beforeEnter组件内守卫beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave最常见的面试题是“如何实现登录权限控制”。我一般这样回答用全局前置守卫router.beforeEach在跳转前检查路由的meta信息。如果路由需要登录而当前没有token就跳转到登录页同时记录下原本要跳转的地址登录成功后再回跳。如果有token但用户访问的是登录页就直接跳到首页。如果涉及动态权限还需要在路由守卫里根据用户角色过滤出可访问的路由通过router.addRoutes动态添加到路由表中。这个操作有一个细节addRoutes是异步的所以需要在守卫里判断路由是否已添加完成否则刷新页面后首次跳转可能会白屏。6.3 关键词“vue2 iframe 缓存”的实际场景热词里有一个“vue2 iframe 缓存”的问题我实际项目里也踩过坑。在Vue2中用iframe嵌入第三方页面时如果切换路由再切回来iframe会重新加载用户体验很差。要解决iframe缓存有几个实用方案用keep-alive缓存iframe所在的组件。注意iframe组件内部状态仍然会保留但需要确保iframe的src不随着路由变化而变化。把iframe的DOM节点挂到组件外面用v-show控制显示隐藏避免销毁重建。动态设置src切换前把src清空再切换回来时重新赋值配合v-if和nextTick。面试时被问到iframe缓存问题不妨把自己踩坑的过程讲一遍会显得更有实战经验。7. Vue2 vs Vue3现在面试绕不开的对比题2023年面试Vue2岗位面试官基本都会追问一嘴Vue2和Vue3的区别。这道题不难但要答得全面也不是一聊就能聊完的。我总结了几个高频角度大家可以直接用来当回答骨架。7.1 响应式实现defineProperty vs Proxy这是最核心的区别。Vue2基于Object.defineProperty只能劫持已有的属性无法监听属性的新增和删除数组的索引变化也监听不到所以需要额外的$set和数组方法重写。Vue3基于Proxy可以代理整个对象所以新增属性、删除属性、数组索引变化都能被监听到。而且Proxy的性能理论上比defineProperty更好因为它是懒代理访问到嵌套对象时才去递归代理初始化成本更低。这里有个细节Vue3的Proxy也不是完全没有代价的它不能代理一些非对象的值所有你用ref来包裹基本类型。不过这不是重点面试时一句话带过就行。7.2 API设计Options API vs Composition APIVue2的组件代码按options组织data、computed、methods、watch、lifecycle hooks都分别放。小组件还好但当一个组件逻辑复杂时你会发现一个功能的代码被拆散到了各个options里组件越大越难维护。Vue3的Composition API按“逻辑关注点”组织代码你可以把实现统一功能的响应式变量、computed、watch、生命周期都写在一起代码聚合度高得多。而且逻辑可以通过自定义hook函数复用到其他组件。面试官常问“Vue3的setup和Vue2的created有什么区别”我的回答是setup的调用时机比beforeCreate更早它发生在props解析之后、组件实例创建之前。在setup里不能直接访问this因为它是在组件实例创建之前执行的。至于替代createdsetup中直接写同步逻辑即可created可以做的事情setup都能做。7.3 生命周期和全局API的变化Vue3把Vue2的beforeDestroy和destroyed改成了beforeUnmount和unmounted语义更准确。对应的组合式API里是onBeforeUnmount和onUnmounted。全局API也有一些变化。Vue2里是Vue.component(my-component, {}) Vue.directive(my-directive, {}) Vue.mixin({}) new Vue()Vue3改成import { createApp, h } from vue const app createApp(App) app.component(my-component, {}) app.directive(my-directive, {}) app.mixin({}) app.mount(#app)还有Vue3支持多个根节点template里不再要求只能有一个根元素。Vue2只能有一个根节点不然会报错这个在写组件时经常碰到Vue3彻底解决了。7.4 Vue2项目升级Vue3前端代码怎么处理热词里有“vue2升级vue3 前端代码怎么处理更好需要全部替换vue3写法吗”。这个问题在实际项目里特别有共鸣。我的经验是不要想着一次性全部重写也没必要。Vue3提供了vue/compat兼容构建版本可以让你在不完全迁移的情况下运行Vue2的代码。这个模式下你还可以用Options API写代码Vue3本身是兼容Options API的只是推荐使用Composition API而已。所以升级路径可以这样走第一步先把构建工具升级到Vite或Webpack5引入Vue3兼容构建让老代码正常运行。 第二步逐个把组件的破坏性变更解决掉比如filter的移除、事件API的调整、fragment根节点的兼容等。 第三步优先把工具函数、复用逻辑这类纯JS部分改成Composition API组件部分在有重写需求时再逐步迁移。 第四步路由和Vuex升级到对应Vue3版本注意vue-router 4和vuex4的API变更点。所以答案是不需要全部替换成Vue3写法尤其是不需要把Options API全部改成Composition API。Vue3完全支持Options API改造成本在于那些破坏性变更的地方而不是写法风格。8. 工程实战与高频综合题HBuilderX、wangeditor、权限控制这些都会怎么考最后一块内容是热词里那些“实战向”的题目。虽然名字看起来像具体工具但面试官真正考察的通常是你对Vue2工程化能力的综合理解。这些题不像八股更像场景题答得好非常加分。8.1 HBuilderX与Vue2实战项目HBuilderX是DCloud出品的IDE常用来开发uni-app项目而uni-app是基于Vue语法的跨端框架Vue2是其基础版本之一。热词里有“hbuilderx vue2实战项目”面试如果问到uni-app相关经验核心考点还是在Vue2的语法、生命周期、组件通信上只是套了一层uniapp的壳。重点需要理解的是uniapp里生命周期和Vue2生命周期的对应关系onLoad对应beforeCreate/createdonReady对应mountedonUnload对应beforeDestroy/destroyed。如果你做过真实项目这个对应关系一定能讲清楚。面试官在意的是你是否真的写过跨端项目遇到微信小程序端兼容问题时的排查思路是什么。8.2 wangeditor和quill富文本编辑器的集成考点热词里有“vue2使用wangeditor”和“vue2 quill富文本编辑器”。这个方向其实是个经典场景题在Vue2项目中集成编辑器、如何回显数据、如何做图片上传。wangeditor集成需要特别注意的是初始化和销毁时机。我一般是在mounted里初始化编辑器在beforeDestroy里执行editor.destroy()销毁。这是因为编辑器会在DOM上绑定大量事件和生成自己的实例如果不销毁切换到其他路由后这些实例还会存在造成内存泄漏甚至影响页面性能。quill也一样处理图片上传时通常会自定义toolbar拦截image按钮点击用input上传到服务器拿到图片URL后通过quill的insertEmbed方法插入到编辑器内容中。这里有一个比较隐蔽的坑回显时如果内容是带图片的HTML需要在外层样式里给图片设置max-width: 100%否则在移动端或小容器里图片会溢出。这类题目对面试官来说考察的就是你是否真的在项目里处理过这些细节而不仅仅是看文档能说个大概。8.3 其他实战热词速览手写签名、webview扫码、3D地图有些热词看起来比较具体但本质上还是Vue2实战能力的场景延伸手写电子签名核心是Canvas绘图鼠标和touch事件绑定、坐标转换、取消重做逻辑、导出base64图片。在Vue2里要重点处理的是组件销毁时的事件解绑以及移动端touchmove时的preventDefault配合passive: false。微信小程序原生webview加载Vue2页面并调用手机扫码本质是uni-app或小程序web-view与Vue2 H5页面之间的通信。小程序通过postMessage给H5传递消息H5监听message事件调用手机扫码后再把结果返回给小程序。Vue2百度3D实景地图加载3D模型这属于地图API与前端框架结合的场景题核心是用JsSDK在mounted里初始化地图在异步回调中创建3D模型图层。这些题如果项目里没做过硬编很难编得像样。面试时如果碰到最诚实也最加分的回答方式是承认没做过但把实现思路拆解清楚比如“我会先确认地图SDK的API支持什么格式的模型文件然后通过异步加载的方式在Vue的mounted里初始化再把模型渲染和组件生命周期关联起来”。面试官更看重的是你的思考路径和排查能力而不是具体工具的操作步骤。8.4 动态路由与按钮级权限的完整方案最后补一道工程面试题也是热词“vue2主应用 vue3子应用路由异常”经常引出的权限方案题。动态路由权限的实现我常用的做法分两个维度路由级的权限控制路由表拆成constantRoutes所有用户都能访问比如登录页、404页、首页和asyncRoutes需要权限判断的页面。登录成功后根据用户角色过滤出可访问的asyncRoutes。通过router.addRoutes(asyncRoutes)动态添加。在全局守卫里判断当前路由是否已添加避免刷新后白屏。按钮级的权限控制通过自定义指令v-permission指令的值是需要的权限标识。在inserted钩子里通过this.$store.getters.permissions或从localStorage里取判断当前用户是否有这个权限没有就el.parentNode.removeChild(el)。或者可以用组件封装的AuthButton包裹按钮内部判断无权限时不渲染子内容。这里容易踩的坑是路由动态添加过程中如果用户刷新页面Vuex里的权限数据会丢失所以需要把用户信息和权限标识持久化到localStorage或sessionStorage里刷新后再从存储里恢复然后重新addRoutes。“vue2主应用 vue3子应用路由异常”这种问题本质是微前端架构下主应用和子应用的路由管理问题。常见原因有子应用在独立运行时正常但嵌入主应用后就找不到路由了。排查思路一般是检查activeRule配置是否冲突检查主应用的base路径是否被正确传递给子应用路由检查子应用是否使用了memory/abstract history模式。这类问题在微前端场景中很常见面试官抛出这个题往往是想看你的调试基本功。9. 面试前的速记清单与复盘写到这里我把2023年实际面试中最高频的Vue2问题整理成一个快速自查表适合在面试前一天快速翻一遍。基础概念如果没掌握先补基础如果基础已经OK重点看对比分析和原理机制。考点核心结论追问方向响应式原理Object.defineProperty Dep Watcher新增属性怎么办数组索引为什么监听不到computed缓存lazy watcher dirty标志依赖变化时computed会立刻重新计算吗watch与computed异步/开销大用watch同步计算用computeddeep监听性能问题生命周期顺序父beforeCreate→子created→子mounted→父mounted你会在updated里做什么要注意什么nextTick数据更新异步队列DOM更新后回调为什么微任务优先组件通信props/emit/eventBus/provide/inject/$attrsv-model语法糖怎么理解diff算法同层比较 首尾指针 key为什么不建议index作为keyVuexstate/getters/mutations/actions为什么mutation必须同步Vue2 vs Vue3defineProperty vs Proxy升级项目要全部重写吗权限控制路由守卫 addRoutes 自定义指令刷新后白屏怎么解决如果你在准备面试我强烈建议不要死记硬背而是把上面每个点都结合自己的实际项目场景讲一遍。比如你做过一个表格组件那就从数据结构设计开始讲顺便讲响应式、props校验、事件emit、render函数、solt插槽、功能扩展这一套下来面试官想不给你加分都难。八股是骨架项目经验是血肉。两者结合着讲才能既通过技术面又让面试官相信你入职后能真的干活。

相关新闻

DBSCAN聚类算法MATLAB实现:从原理到参数调优

DBSCAN聚类算法MATLAB实现:从原理到参数调优

2026/8/31 19:03:19

简介:本资源是一份面向数据科学初学者与MATLAB用户的DBSCAN密度聚类算法实现代码包,聚焦无监督学习中任意形状聚类与噪声识别这一典型问题,特别适用于地理信息、异常检测、图像分割等含噪声且簇结构复杂的实际场景。压缩包共3个文件&#xff…

没人可说?分层倾诉渠道帮你找到情绪出口

没人可说?分层倾诉渠道帮你找到情绪出口

2026/8/31 19:03:19

简介:本资源是一个基于Modbus TCP/IP协议的VC6.0客户端监控程序源码包,面向工业自动化领域初/中级开发者及嵌入式通信学习者,解决Modbus设备网络化调试、实时数据读写与通信状态可视化等实际工程问题。压缩包共54个文件,含16个头文…

从背八股文到懂底层原理:HashMap、MySQL、Kafka核心机制深度拆解

从背八股文到懂底层原理:HashMap、MySQL、Kafka核心机制深度拆解

2026/8/31 19:03:19

1. 为什么我只把八股文当成面试的入场券 做了这么多年技术面试官,我最大的感触就是:现在很多人把背八股文当成了学习的终点,而不是起点。你问他HashMap的put流程,他能从头到尾背得一字不差,什么扰动函数、扩容阈值、红…

三极管实现5V转3.3V电平转换电路详解与面试要点

三极管实现5V转3.3V电平转换电路详解与面试要点

2026/8/31 20:23:22

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

STM32F103驱动ATT7022E/HT7036电能计量芯片:硬件设计、SPI驱动与校准实战

STM32F103驱动ATT7022E/HT7036电能计量芯片:硬件设计、SPI驱动与校准实战

2026/8/31 20:23:22

简介:本资源面向嵌入式电力仪表开发工程师与高校电能计量方向学习者,提供基于STM32F103C8T6主控、ATT7022E三相电能计量芯片及HT7036电力线通信芯片的完整硬件设计与软件实现参考方案,解决电能参数高精度采集、本地处理与PLC远程传输的一体化…

黑夜下的海上执法之眼:热成像船舶再识别与可疑活动检测新框架

黑夜下的海上执法之眼:热成像船舶再识别与可疑活动检测新框架

2026/8/31 20:23:22

论文标题:Vessel Re-identification and Activity Detection in Thermal Domain for Maritime Surveillance 作者:Yasod Ginigea、Ransika Gunasekara、Darsha Hewavitharana、Manjula Ariyarathne、Ranga Rodrigo、Peshala Jayasekara(斯里兰卡莫拉图瓦大学) 发布:arXiv:2406.…

SimCLR自监督与监督学习对比:TinyImageNet实验解析

SimCLR自监督与监督学习对比:TinyImageNet实验解析

2026/8/31 20:23:22

简介:本资源是一项面向深度学习初学者与图像算法研究者的对比实验项目,聚焦自监督学习在标注数据受限场景下的可行性验证。项目完整实现了SimCLR对比学习框架,在TinyImageNet数据集上对ResNet18模型进行无监督预训练,并与同结构监…

布林回归信号:创始人模式驱动AI自我进化

布林回归信号:创始人模式驱动AI自我进化

2026/8/31 20:23:22

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

【YiFeiWebApi】YiFeiWebApi接口安装说明

【YiFeiWebApi】YiFeiWebApi接口安装说明

2026/8/31 20:13:22

YiFeiWebApi接口安装说明 一、 数据库配置文件修改二、 IIS环境配置(建议IIS7.0)三、 安装.NET 10.0 运行时四、 IIS配置站点五、 发布系统六、 测试接口七、测试服务器站点接口八、其他问题查看日志解决九、ApiPost项目文档 一、 数据库配置文件修改 说明: DSCSYSS…

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

备战数据库管理工程师校招:索引、事务、备份恢复核心考点解析

2026/8/31 1:38:25

每年校招季我都会接触不少准备数据库方向笔试的同学,看到最多的状态就是:简历上写着“熟悉 MySQL”“了解索引优化”,一碰到数据库管理工程师的笔试卷,却在索引、事务、锁、备份恢复这些题目上翻车。网易这套 2018 校园招聘数据库…

数字电路时序基石:深入理解建立时间与保持时间

数字电路时序基石:深入理解建立时间与保持时间

2026/8/31 7:20:57

1. 这不是“背公式”的事:时间参数到底在约束什么你翻过数字电路教材,一定见过这两个词:建立时间(Setup Time)和保持时间(Hold Time)。它们常被并列写在触发器(Flip-Flop&#xff09…

蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

蓝桥杯国赛超声波测距机:从单片机原理到嵌入式系统实战

2026/8/31 17:18:46

1. 项目缘起:从赛题到超声波测距机的诞生第八届蓝桥杯单片机设计与开发国赛的题目,我至今记忆犹新。它没有直接给出一个花哨的名字,而是用“超声波测距机”这个朴实无华的功能描述,精准地勾勒出了考核的核心。对于当时备赛的我而言…

MCU无DAC如何用定时器+DMA 2D输出高保真任意波形

MCU无DAC如何用定时器+DMA 2D输出高保真任意波形

2026/8/31 0:02:27

接到一个仪表类项目,要在 LAT1189 上输出几种不同波形:正弦、三角、带可调死区的脉冲,频率和幅度都得能实时改。板子上没有 DAC,就一个定时器加几个 DMA 通道。我一开始觉得在定时器中断里改比较寄存器也能应付,后来把…

Cortex-M3 Flash下载失败?从编程错误标志到供电瞬态排查

Cortex-M3 Flash下载失败?从编程错误标志到供电瞬态排查

2026/8/31 0:02:27

前两周调试一块带着Cortex-M3内核的板子,IDE里下载固件时突然弹出一行刺眼的错误: error: flash download failed - cortex-m3 。这种报错在嵌入式开发里太常见了,常见到很多人第一反应就是换根数据线、重插一下调试器,但重启三…

STM32 TouchGFX屏幕切换Transition优化:原理、配置与排障实战

STM32 TouchGFX屏幕切换Transition优化:原理、配置与排障实战

2026/8/31 0:02:27

做STM32 GUI开发的朋友应该都有体会——界面搭得再漂亮,一旦屏幕切换卡成PPT,整个产品的档次瞬间就没了。早期我在LAT1212这个基于STM32的GUI工程上用TouchGFX做二次开发,最头疼的不是画界面,而是怎么让切换动画既流畅又自然。Tou…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/31 17:18:51

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/31 17:18:48

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/31 17:18:48

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…