每天10道题,100天后,搞定所有前端面试的高频知识点,加油!!!,在看文章的同时,希望不要直接看答案,先思考一下自己会不会,如果会,自己的答案是什么?想过之后再与答案比对,是不是会更好一点,当然如果你有比我更好的答案,欢迎评论区留言,一起探讨技术 之美。
目录
面试官:请简述一下vue-router路由钩子函数是什么?执行顺序是什么?
面试官:请简述一下vue-router组件复用导致路由参数失效怎么办?
面试官:请简述一下Vue2中的响应式数据的原理
我:呃~,在vue2中响应式数据的原理主要基于Object.defineProperty这个ES5的特性,当创建vue实例时,vue会遍历data对象的属性,使用Object.defineProperty可以将它们转换为getter和setter并对属性值进行监控。
getter函数:当访问属性值时,getter函数会被调用,Watcher会被添加到Dep对象的subs数组中,表示这个Watcher依赖于这个属性。
setter函数:当属性值发生变化时,setter函数会被调用,通知Dep对象,Dep对象再通知所有依赖于这个属性的Watcher,让它们更新视图。
总之:vue2中的响应式数据的原理是通过使用Object.defineProperty()对data对象的属性进行劫持,建立属性与依赖之间的关系,从而实现了数据驱动视图的自动更新。
面试官:请简述一下Vue3中的响应式数据的原理
我:呃~,在vue3中响应式数据的原理主要基于ES6的Proxy对象,相较于vue2中的Object.defineProperty,vue3采用Proxy来实现对数据的劫持和响应式处理,Proxy对象允许一些自定义操作行为,如属性查找、赋值等。当创建vue3实例时,vue3会使用Proxy对象包装data对象,每次访问或修改被Proxy包装的data对象时,都会触发相应的拦截器函数。
总之:vue3的响应式数据的原理是基于Proxy对象,通过代理数据对象,监听数据的访问和修改,并在数据变化时触发相应的更新操作,从而实现了数据驱动视图的自动更新。相比v2在性能和扩展性上都有所提升。
面试官:请简述一下Vue是如何检测数组变化?
我:呃~,vue使用不同的方式来检测数组变化,具体取决于我们对数组的操作方式,如下:
vue2:在v2中使用了一种叫做 “响应式追踪” 的机制来检测数组变化,通过对数组使用的操作方法来修改数组,vue能够就能检测到数组的变化,举例函数如下:
push()、pop()、shift()、unshift()、splice()、sort()、reverse()
因为vue通过重写这些方法,使其在执行时可以触发通知,告知vue有关数组的变化。这样,vue就能够在数据发生变化时及时更新视图,然而对于直接通过索引或者length属性修改数组元素的方式,vue是无法进行检测的。
vue3:在v3中借助ES6的Proxy对象,vue可以更加精确地追踪数组的变化,对于数组的任何修改,包括直接通过索引或length修改,都可以被Proxy对象捕捉到,从而实现更加完备的数组变化检测。
总之:vue通过重写数组的变异方法或者使用proxy对象来检测数组的变化,以便在数据发生变化时及时更新视图。
面试官:请解释Vue的父子组件生命周期钩子函数执行顺序?
我:呃~,Vue的父子组件生命周期钩子函数执行顺序在Vue 2和Vue 3中有一些差异,但整体原则保持一致。下面将分别解释Vue 2和Vue 3的父子组件生命周期钩子函数的执行顺序:
Vue2:
1)创建和挂载阶段:
父组件:beforeCreate -> created -> beforeMount
子组件(在父组件的beforeMount之后):beforeCreate -> created -> beforeMount -> mounted
父组件(在所有子组件的mounted之后):mounted
2)更新阶段:
父组件:beforeUpdate
子组件(在父组件的beforeUpdate之后):beforeUpdate -> updated
父组件(在所有子组件的updated之后):updated
3)销毁阶段:
父组件:beforeDestroy
子组件(在父组件的beforeDestroy之后):beforeDestroy -> destroyed
父组件(在所有子组件的destroyed之后):destroyed
Vue3:
1)创建和挂载阶段:
父组件:beforeCreate -> created -> beforeMount
子组件(在父组件的beforeMount之后):beforeCreate -> created -> beforeMount -> mounted
父组件(在所有子组件的mounted之后):mounted
2)更新阶段:
父组件:beforeUpdate
子组件(在父组件的beforeUpdate之后):beforeUpdate -> updated
父组件(在所有子组件的updated之后):updated
3)销毁阶段:
父组件:beforeUnmount
子组件(在父组件的beforeUnmount之后):beforeUnmount -> unmounted
父组件(在所有子组件的unmounted之后):unmounted
面试官:请简述一下v-model双向绑定的原理是什么?
我:呃~,v-model指令是vue中用于实现表单输入元素和应用状态之间双向绑定的一个重要工具,其原理可以简单概括如下两个核心点:
1)监听输入事件并更新数据 2)数据变化时更新视图
具体来说,v-model 的工作原理可以归纳为以下几个步骤:
1)绑定数据
2)监听输入事件
3)更新数据
4)视图更新
总之:v-model 的双向绑定原理是通过监听表单元素的输入事件来更新数据,同时当数据发生变化时自动更新视图来实现的。这种机制使得表单元素和vue实例数据之间能够保持同步,从而简化了表单数据的处理流程。
面试官:请简述一下vue-router路由钩子函数是什么?执行顺序是什么?
我:呃~,路由钩子函数是一组可以在路由导航过程中进行拦截和处理的函数,它们允许您在路由导航发生前、发生时或发生后执行逻辑。
vue-router提供了三种类型的路由钩子函数:全局前置守卫、全局解析守卫和全局后置钩子。
它们的执行顺序如下:
在执行顺序上,全局前置守卫会在路由切换开始之前先执行,然后是路由独享守卫,最后是组件内路由守卫,在路由切换过程中,这些路由钩子函数会按照定义的顺序依次执行。
1)全局前置守卫(beforeEach):在路由切换开始前执行。可以用来进行导航守卫,比如进行权限控制或者页面切换前的逻辑处理。
2)路由独享守卫(beforeEnter): 在特定路由配置中定义的守卫函数。与全局前置守卫类似,但仅应用于特定路由。
3)组件内路由守卫(beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave): 在组件内部定义的路由钩子函数,用于处理特定组件内的路由变化逻辑。
这些路由钩子函数使得开发者能够在路由切换的不同阶段执行逻辑,从而实现诸如路由权限控制、页面加载前的数据预取等功能。
面试官:请简述一下vue-router动态路由是什么?
我:呃~,是指在路由路径中包含变量部分,这些变量部分可以根据实际情况动态地匹配不同的路径,从而实现更加灵活的路由配置。
通过使用动态路由可以实现诸如根据不同的用户ID加载不同的用户详情页面、根据不同的产品ID加载不同的产品详情页面等功能。
动态路由示例如下:
假设我们有一个用户详情页面,其路由路径为/user/:id,其中:id就是动态部分,它代表了一个用户的特定ID。当用户访问/user/123时,:id会被匹配为123,而当用户访问/user/456时,:id会被匹配为456,以此类推。
总之:动态路由为我们提供了一种灵活且简洁的方式来处理路由路径中的变量部分,使得我们能够更好地应对不同路径的匹配需求。
面试官:请简述一下vue-router组件复用导致路由参数失效怎么办?
我:呃~,组件复用可能导致路由参数失效的情况,这种情况通常发生在同一个组件在不同路由间切换时,由于组件实例的复用,导致原来的路由参数仍然存在于组件内部,而没有被更新为新的路由参数,为了解决这个问题,可以采取以下几种方法:
1)使用watch监听路由变化:
在组件内部使用watch或者beforeRouteUpdate等功能,监听路由参数的变化,在参数变化时手动更新组件内部的数据。
2)使用beforeRouteEnter守卫:
在路由配置中使用beforeRouteEnter守卫,通过回调函数获取组件实例,然后在回调函数内部处理路由参数的变化。
3)使用key属性强制组件重新渲染:
在路由视图组件中,可以通过给组件添加key属性,并将其设置为$route.path,这样可以强制Vue重新渲染该组件,从而避免组件复用导致的路由参数失效问题。
4)使用beforeRouteLeave守卫做清理工作:
在组件离开路由时,可以使用beforeRouteLeave守卫对组件内部的状态进行清理,以确保下次组件被复用时不会受到之前路由参数的影响。
通过以上方法,可以有效地解决组件复用导致路由参数失效的问题,确保路由参数能够正确地传递和更新到组件内部,从而维持良好的路由导航体验。
面试官:Vue生命周期钩子是如何实现的?
我:呃~,生命周期钩子是Vue实例在创建、更新和销毁过程中自动调用的函数。这些钩子允许开发者在Vue实例的不同阶段执行特定的代码,从而实现对Vue实例及其子组件生命周期的管理,开发者只需要在Vue实例或组件的选项中定义相应的钩子函数即可。这些钩子函数在Vue实例或组件的生命周期中的特定阶段被自动执行,从而允许开发者在这些阶段执行特定的代码。
面试官:如何理解Vue中的模板编译原理?
我:呃~,模板编译原理是指将vue模板转换为渲染函数的过程。在vue中模板编译是在运行时进行的,vue实例在创建时,会将模板字符串经过编译器编译成渲染函数,然后再执行渲染函数生成虚拟dom,并最终渲染成真实的dom,模板编译的主要过程包括以下几个步骤:
1)模板解析:vue的编译器会先将模板字符串解析成抽象语法树(AST),根据模板中的标签、指令、文本内容等信息构建出一个语法树结构。
2)静态标记:编译器会对抽象语法树进行静态标记,识别出哪些节点是静态的,即在每次重新渲染时不会发生变化的部分。
3)代码生成:根据解析后的抽象语法树,编译器会生成可执行的渲染函数,这个渲染函数可以接收数据作为参数,并返回虚拟dom。
4)渲染函数执行:当vue实例需要更新视图时,会执行之前生成的渲染函数,传入最新的数据,渲染函数会生成新的虚拟dom,并与之前的虚拟dom进行对比,计算出需要更新的部分,然后将更新应用到真实的dom上。
通过模板编译,vue实现了将模板转换为渲染函数的过程,这样做的好处是避免了每次数据变化都重新解析模板,提高了渲染的效率。同时vue的模板编译也支持一些高级特性,例如条件渲染、循环、事件处理等,使得开发者可以通过简洁而直观的模板语法来描述视图,而无需关心底层的渲染逻辑。