Vue前端面试题

1.谈谈vue的生命周期,每个生命周期都在做什么?

回答:vue的生命周期一般就是八个beforecreate、created、beforemount、mounted、beforeupdate、updated、beforedestroy、destroyed。如果使用vue3的setup的话,beforecreate、created就不需要单独拿出来了,直接写进<script setup></script>中就行了,其余的生命周期就需要import进来。每个生命周期都在做什么,关于beforecreate,网上给出的作用是在实例创建之前进行一些数据初始化,因为此时还获取不到data,所以一般使用默认值或者从后段获取初始化数据、还可以用来做一些组件的依赖注入,例如this.$options.inject获取注入的属性或方法实现组件间通信、获取数据,又或者在此处做一些页面拦截。关于created,那就是此时进行初始化data和methods。关于beforemount,此时模板是准备好的,但是还没有挂载上,此处还可以做一些数据的修改。关于mounted,此时页面已经渲染并挂载上,已经可以获取到dom元素,所以我们可以在此处获取dom进行操作。关于beforeupdate,这个生命周期需要对数据进行更新修改时才会触发,在此处我们可以对数据进行最后的修改。关于updated,此时已经更新完毕,我们可以在此处获得最新的dom结构。关于beforedestroy,这个生命周期是进行销毁触发的,在此处我们通常对定时器清除、事件解除绑定、解除监听等等操作。关于destroyed,与beforedestroy差不多,都是在这里做定时器清除、事件解除绑定、解除监听。不过要注意,如果你希望页面缓存下来而不是销毁,可以用keepalive包裹住要保留的组件,可以让组件不被销毁,下次调用就不需要重新创建。keepalive中还有两个生命周期,分别是activated缓存的组件激活时执行、deactivated缓存的组件失活时执行,我的理解这是代替beforedestroy和destroyed的。

2.什么是双向数据绑定,是怎么实现的?

回答:双向数据绑定在我的理解就是input的数据发生变化,显示在视图上也有变化。v-model就可以实现双向数据绑定。底层实现就是@input+v-bind:value结合起来。再底层就是使用defineProperty或proxy进行数据劫持,劫持到数据发生改变了,触发视图的变化。

3.了解虚拟DOM吗,是干什么的,和真实dom有什么区别。

回答:虚拟dom就是避免直接修改dom而诞生的操作,本质是使用js对象来编写dom节点(大致就是tag、props、children三个属性),然后在数据发生改变时,先在虚拟dom(js)上计算出变更的部分,然后将要修改的部分提交上去,再进行dom操作。虚拟dom虽然增加了这些步骤、虽然并没有直接操作dom更加快速,但是它可以尽可能的避免真实dom进行重绘、回流的次数。本质还是为了性能考虑,减少频繁且大面积的重绘引起的性能问题。

4.watch侦听器是干什么的,什么是深度监听,如何实现?

回答:watch侦听器可以实现对简单数据类型的监听、也可以监听引用数据类型,但是需要设置额外的deep:true,也可以直接对对象的具体的键进行监听。可以在侦听器中设置操作,并且可以获取到新值和旧值(引用类型除外)、引用类型栈中存放的是地址,所以无法获取新值和旧值,每次都是新值。

5.有用过插槽吗,插槽有哪几种类型,如何使用?

回答:使用过,插槽分为具名插槽、作用域插槽、默认插槽。例如在父组件中引入并使用了子组件,可以在子组件的标签(双标签)中写入内容(该内容需要是父组件本身或者是获取到的),然后在子组件中需要显示改内容的位置写上<slot></slot>标签,就可以实现插槽的使用。同时写多个slot会显示多次重复内容,如果想要在指定区域放指定内容,就需要具名插槽。具名插槽:父组件处加上slot属性的名称例如<template v-slot:header>头部</template> ,此时子组件使用<slot name='header'></slot>就可以实现对应内容出现在对应区域。此外关于作用域插槽,如果我们希望子组件能拿到父组件的值,可以在子组件<slot>标签中加上属性,父组件中的子组件标签上加上v-slot='slotporps' ,就可以通过slotporps.属性名来获取。如果要简化不想使用.方法,可以使用结构,例如子组件中传的是url,则父组件v-slot="{url}"就可以直接结构出来,然后使用url。

6.了解keepalive吗,用在哪些场景、有什么作用呢?

回答:keepalive可以让组件缓存起来,避免多次重复的请求。一般是缓存那些不需要改变的组件。包裹起来的组件不会被销毁,生命周期没有beforedestroy和destroyed但是有activated和deactivated。可以使用include白名单和exclude黑名单,传入正则或者字符串,include会让名字匹配的组件缓存、exclude会让名字匹配的组件都不缓存,其余的都缓存。使用场景,比如购物页面中,我们从首页进入商品列表页再进入商品详情页,此时退出返回到列表页再返回首页都可以使用缓存,此时就可以按需控制keepalive。

7.vuex是干什么的,有什么用,怎么使用?

回答:vuex是一个全局状态管理的工具,它的出现就是为了我们能够在任何组件,任何位置都能获取到状态信息,避免两个不相干的组件要进行复杂的通信。通过创建一个store实例,只需要提供state、mutation就可以使用了,在组件中就可以通过this.$store来访问store实例的数据,然后通过this.$store.commit('mutation中方法名')调用mutation里的方法来修改store中state的数据。关于获取state,在子组件中通常都是要this.$store.state.数据名,这样书写十分复杂,所以引入mapState,可以简写,在mapState函数中直接用store.属性名就可以访问。getter相当于store的计算属性,getter中定义的方法可以直接通过store.getters.方法名来使用。对应的也有mapGetters函数来让书写更方便。mutation就是唯一的更改store中数据的方法,通过store.commit('方法')就可以使用mutation中的函数。如果有参数就在后面加逗号和参数就行例如store.commit('方法',参数),同样有mapMutation方法来简化书写,不过要记住mutation只能写同步的方法,异步的方法要统一写在action中,action提供了一个参数与store对象具有相同方法和属性的 context 对象的context(执行上下文),能够通过context.commit可以调用mutation中的方法,context.getters、context.state也可以获取到getters和state,子组件要触发action就需要this.$store.dispatch('方法名'),同样有mapActions函数实现简写,由于action可以是异步的,所以进行异步操作时是可以搭配.then接收异步结果、或者async、await组合使用的。

8.proxy和defineProperty的区别是啥?为什么vue3用的proxy呢?

回答:proxy和defineProperty都能实现数据劫持,他们也是响应式实现的重点核心。vue2之所以使用defineProperty可能是时代原因,在vue2创建初期没有proxy,不然肯定也是用proxy的。proxy在性能方面应该是优于defineProperty的,此外defineProperty想要监听到引用类型的深层拦截,是需要递归的,而proxy可以直接劫持到引用类型的属性实现深度监听,另外关于后续出现的新类型map和set,proxy也都能很好的实现拦截。当然proxy也有一点,就是无法兼容老版本的IE浏览器,这一点是需要考虑的。proxy的本质是使用get、set、deleteProperty三个方法来劫持数据的,而Object.defineProperty本质只有get和set。proxy能够简单的实现增删改查,而defineProperty还需要我们自己去实现删除功能。综合多种原因,最终vue3使用proxy。

9.v-for和v-if为什么不能一起使用,有什么问题吗?

回答:在学习这两个指令之初,就被处处提醒不能一起用,一起用会有问题。具体的问题是什么、咋产生的呢。最根本的原因是优先级的原因,v-for会比v-if优先执行,如果v-if为true还好,如果v-if为false,最终不渲染这个dom节点了还要删除节点,则会产生性能上的浪费,以及页面卡顿。简而言之就是v-for会先执行,然后创建dom,再通过v-if判断是否要渲染,这种行为会让v-for浪费,并且实际中如果v-for创建的dom结点多,还会导致页面卡顿白屏等等。

10.Composition Api 和option Api的区别在哪里?

回答:在刚刚学习vue时,使用的是选项式api(option api),它能够规范我们的思路与代码风格,写数据的地方就写数据、写方法的地方写方法、通信的地方写通信数据,监听的地方写监听,这样看起来更加的规范,但是一旦数据量大、处理方法多就会导致杂乱,方法和数据对应不上,这里写一点那里写一点,不利于后续维护。所以组合式api的出现,一定程度上解决这个问题,我们就像是书写普通js逻辑一样,在一定的区域处理部分业务,比如登录业务的数据、方法写一起,购物车的业务代码写一起,便于我们后续查看检查。此外组合式api还更加支持ts。

11.组件通信都有什么方法?

回答:父子组件通信的方法有:1.props+$emit,在父组件中将数据写在<子组件>上,子组件通过props接收父组件传来的属性,就可以进行使用,如果需要修改,那就要在子组件中使用this.$emit('方法名',参数),父组件的<子组件>里就使用@方法名来接收。2.回调函数,在父组件中将数据和方法都直接写在<子组件上 :message="dnaskjnda"  :changefn=''父组件中方法名">,在子组件中props接收数据和方法,然后直接绑定该方法就可以调用父组件的方法。3.$parent和$children访问父组件和子组件的属性。4.provide和inject,父组件中provide,子组件inject。5.$attrs + $listeners,多用于爷孙通信吧。5.ref和refs,父组件的<子组件 ref="child"> ,假设子组件有age,name属性。父组件就可以在下方通过this.$refs.child.age,this.$refs.child.name访问到子组件的age和name。最方便最常用。兄弟组件以及其他复杂关系的,推荐用全局事件总线、vuex、pinia来通信。

12.了解$nextTick吗,其底层是如何实现的?

回答:$nextTick就是一个等待dom更新的工具,如果我们使用异步的方法修改了dom,立即打印的结果并不是最新的,想要获得最新的dom节点、需要在前面使用nextTick()方法,然后再console就可以获得最新更新后的数据。具体使用场景应该就是created中获取最新数据、响应式数据变化后要获取dom最新的值。nextTick(回调函数),会返回一个promise,所以后续还可以使用 .then,async\await方法。底层原理就是,vue在数据发生变化时,并不会立即更新dom,而是开启一个队列,将要更新的函数放入队列中,然后当同步任务执行完只会再执行队列中的任务,这就导致我们无法获取最新的dom,nextTick就是获取队列中的任务然后执行,后面的同步任务也需要等待其执行完毕,所以能够获取到最新的dom。

13.vue-router用来干什么的,你是否使用过?

回答:有使用过,router是路由管理对象,route则是某一条路由。在路由跳转时,就可以设置规则进行拦截,实现路由守卫的功能,还可以使用路由传参。本质上来说,一个项目要跳转路由,就会用到vue-router。vue-router是一个很大的概念,他是vue官方路由,具体可以实现的功能有

  • 嵌套路由映射
  • 动态路由选择
  • 模块化、基于组件的路由配置
  • 路由参数、查询、通配符
  • 展示由 Vue.js 的过渡系统提供的过渡效果
  • 细致的导航控制
  • 自动激活 CSS 类的链接
  • HTML5 history 模式或 hash 模式
  • 可定制的滚动行为
  • URL 的正确编码
  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue是一个流行的前端框架,以下是对Vue生命周期的理解: Vue的生命周期包括了创建、挂载、更新和销毁等不同的阶段。在每个阶段,Vue都会触发相应的生命周期钩子函数,我们可以在这些函数中执行相关的操作。 - 创建阶段:Vue实例初始化,包括数据的观测、事件的初始化等。在这个阶段,可以使用beforeCreate和created钩子函数来执行一些初始化操作,但此时DOM元素还未挂载。 - 挂载阶段:在挂载阶段,Vue将编译好的模板挂载到DOM元素上,并将数据渲染到视图上。在挂载阶段,可以使用beforeMount和mounted钩子函数来执行相关的操作。beforeMount在挂载之前被调用,此时虚拟DOM已经创建好,但还未替换真实DOM;而mounted在挂载之后被调用,此时真实DOM已经插入到页面中。 - 更新阶段:当数据发生变化时,会触发更新阶段。在这个阶段,Vue会重新渲染视图以反映最新的数据。可以使用beforeUpdate和updated钩子函数来执行相关的操作。beforeUpdate在数据更新之前被调用,此时虚拟DOM已经更新完成,但还未应用到真实DOM;而updated在数据更新之后被调用,此时视图已经更新完成。 - 销毁阶段:在销毁阶段,Vue实例被销毁,包括清除定时器、解绑事件等。可以使用beforeDestroy和destroyed钩子函数来执行相关的操作。beforeDestroy在实例销毁之前被调用,此时实例仍然可用;而destroyed在实例销毁之后被调用,此时实例已经被完全销毁。 总结来说,Vue的生命周期钩子函数提供了一系列的时机,方便我们在不同的阶段执行相关的操作,使得我们能更好地控制和管理Vue应用的生命周期。详细的内容可以参考中提供的博客链接。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【前端面试】39道Vue高频面试题,亲测有效!!!快来看看呀!!](https://blog.csdn.net/weixin_43352901/article/details/108210170)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值