Vue 面试题汇总(一)

简介: Vue 面试题汇总(一)

前言

面试题整理自  Vue面试专题,题解结合了个人的思考和理解,供大家参考。

个人觉得村长的题目选的都挺好的,而且题解也很全面,就是题解比较书面,大家实际面试的时候可以尽量口语化,按照答题思路组织语言,把答案附上自己的风格说出来,关于面试技巧有些话复述不出来还可以通过举例的方式表达等等等。。。

题目的顺序是按照观众点赞评论收藏等数据计算出的评分按大到小排名的,排在前面的题目相对更重要观众更感兴趣

花了挺大劲整理的,面试前可以看看 就酱~ (我恨八股文)

1. 简述 Vue 生命周期

答题思路:

  1. Vue 生命周期是什么?
  2. Vue 生命周期有哪些阶段?
  3. Vue 生命周期的流程?
  4. 结合实践
  5. 扩展:在 Vue3 中生命周期的变化

回答范例:

  1. 生命周期这个词应该是很好理解的,在我们生活中就会常常碰到,比如谈到一个人的生命周期,我们会说人这一生会经历婴儿、儿童、少年、青年、中年、老年这几个阶段。 而 Vue 的生命周期也是如此,在 Vue 中的每个组件都会经历从创建挂载更新再到销毁这几个阶段,而在这些阶段中,Vue 会运行一种叫做生命周期钩子的函数,方便我们在特定的阶段有机会添加上我们自己的代码。
  2. Vue 生命周期总共可以分为 8 各阶段:创建前后挂载前后更新前后销毁前后,以及一些特殊场景的生命周期(keep-alive 激活时捕获后代组件错误时)。Vue3 中还新增了三个用于调试和服务端渲染场景
  3. 这几个阶段对应的钩子函数 API依次为:beforeCreatecreatebeforeMountmountedbeforeUpdateupdatedactivated(keep-alive 激活时调用)deactivated(keep-alive 停用时调用)beforeDestorydestoryederrorCaptured(捕获子孙组件错误时调用)
    在 Vue3 中的变化 绝大多数只要加上前缀 on 即可,比如 mounted 变为 onMounted,除了 beforeDestroydestroyed 被重新命名为 beforeUnmountunMounted(这样与前面的 beforeMountmounted 对应,强迫症表示很赞🤣)
  4. beforeCreate 在组件创建前调用,通常用于插件开发中执行一些初始化任务;created 组件创建完毕调用,可以访问各种数据,请求接口数据等;mounted 组件挂载时调用 可以访问数据、dom 元素、子组件等;beforeUpdate 更新前调用 此时 view 层还未更新,可用于获取更新前的各种状态;updated 完成更新时调用 此时view层已经完成更新,所有状态已经是最新的了;beforeUnmount 实例被销毁前调用,可用于一些定时器或订阅的取消;unMounted 销毁一个实例时调用 可以清理与其他实例的链接,解绑它的全部指令以及事件监听器。
  5. 在 Vue3 中: setup 是比 created 先执行的而且没有 beforeCreatecreated

2. Vue 中如何做权限管理

  1. 权限管理一般需求就是对页面权限和按钮权限的管理
  2. 具体实现的时候分前端实现和后端实现两种方案: 前端方案会把所有路由信息在前端配置,通过路由守卫要求用户登录,用户登录后根据角色过滤出路由表,然后在动态添加路由。比如我会配置一个 asyncRoutes 数组,需要认证的页面在路由的 meta 中添加一个 roles 字段,等获取用户角色之后取两者的交集,若结果不为空则说明可以访问。过滤结束后剩下的路由就是用户能访问的页面,最后通过 router.addRoutes(accessRoutes) 方式动态添加路由即可。
    后端方案会把所有页面路由信息存在数据库中,用户登录的时候根据其角色查询得到其能访问的所有路由信息返回给前端,前端再通过 addRoute 动态添加路由信息。
    按钮权限的控制通常会实现一个指令,例如 v-permission,将按钮要求角色通过值传给 v-permission 指令,在指令的 mounted 钩子中可以判断当前用户角色和按钮是否存在交集,有就保留按钮,没有就移除按钮。
  3. 纯前端方案的优点是实现简单,不需要额外权限管理页面,但是维护起来问题比较大,有新的页面和角色需求就要修改前端代码和重新打包部署服务端方案就不存在这个问题,通过专门的角色和权限管理页面,配置页面和按钮权限信息到数据库,应用每次登陆时获取的都是最新的路由信息。

自己的话: 权限管理一般分页面权限和按钮权限,而具体实现方案又分前端实现和后端实现,前端实现就是会在前端维护一份动态的路由数组,通过用户登录后的角色来筛选它所拥有权限的页面,最后通过 addRoute 将动态添加到 router 中;而后端实现的不同点就是这些路由是后端返回给前端,前端再动态添加进去的。 按钮权限一般会实现一个 v-permission ,通过判断用户有没有权限来控制按钮是否显示。 纯前端方案的优点是实现简单,但是维护问题大,有新的页面和角色需求都需要改代码重新打包部署,服务端则不存在这个问题。

3. Vue 中双向绑定的使用和原理

回答思路:

  1. 什么是双向绑定?
  2. 双向绑定的好处?
  3. 在什么地方使用双向绑定?
  4. 双向绑定的使用方式、使用细节、Vue3中的变化
  5. 原理实现描述

回答:

  1. Vue中的双向绑定是一个指令 v-model ,它可以绑定一个响应式数据到视图,同时视图中变化也能改变该值。
  2. v-model 是一个语法糖,它的原理(默认请情况下)就是通过 :value 将变量挂到 dom 上,再通过 input事件 监听 dom 的变化改变变量的值。使用 v-model的好处就是方便呀,减少了大量的繁琐的事件处理,提高开发效率。
  3. 通常在表单上使用 v-model,还可以在自定义组件上使用,表示某个值得输入和输出控制。
  4. 可以结合修饰符做进一步限定(lazy/number/trim),用在自定义组件上时有些不同,它相当于是给了子组件一个 modelValue 的 属性 和 update:modelValue 的 事件; 在 Vue3 中还可以用参数形式指定多个不同的绑定,如 v-model:foo 这个时候就相当于 给了子组件一个 foo 的 属性 和 update:foo 的事件。
  5. v-model作为一个指令,它的原理就是 Vue 编译器会把它转换成 value属性绑定和input的监听事件,上面说过是默认情况下,实际上编译器会根据表单元素的不同分配不同的事件,比如 checkboxradio 类型的input 会转换为 checkedchange 事件。

4. Vue 组件之间通信有哪些?

Vue 组件之间通信有以下这么几种:

  1. props
  2. $emit$on$off$once(后三者在Vue3中已被废除)
  3. $children(Vue3中废除)$parent
  4. $attrs$listeners(Vue3中废除)
  5. ref
  6. $root
  7. eventbus(Vue3中不好使了,需要自己封装)
  8. vuexpinia
  9. provide + inject

以上的方法长按使用场景可以分为:

  1. 父子组件之间可以使用
    props /$emit/ $parent/ ref /$attrs
  2. 兄弟组件之间可以使用
    $parent / $root/ eventbus / vuex
  3. 跨层及组件之间可以使用
    eventbus / vuex pinia / provide + inject

5.你了解哪些 Vue 性能优化方法?

  1. 路由懒加载:有效拆分 App 尺寸,访问时才异步加载
const router = createRouter({
    routes: [
        { path : '/foo', component: () => import('./foo.vue)}
    ]
})
复制代码
  1. keep-alive 缓存页面:避免重复创建组件实例,且能保存缓存组件状态
<keep-alive>
  <router-view v-if="$route.meta.keepAlive == true"></router-view>
</keep-alive>
<router-view v-if="$route.meta.keepAlive != true"></router-view>
复制代码
  1. 使用 v-show 复用 DOM:避免重复创建组件
  2. v-for 遍历避免同时使用 v-if(实际上这在 Vue3 中是错误的写法)
  3. v-oncev-memo: 不再变化的数据使用 v-once;按条件跳过更新时使用 v-memo
  4. 长列表性能优化:如果是大数据长列表,可采用虚拟滚动,只渲染少部分区域的内容。一些开源库(vue-virtual-scroller / vue-virtual-scroll-grid
  5. 事件的销毁:Vue组件销毁时,会自动解绑它的全部指令以及事件监听器,但是仅限于组件本身的事件。
  6. 图片懒加载,自定义 v-lazy 指令 (参考项目:vue-lazyload
  7. 第三方插件按需引入 element-plus 避免体积太大
  8. 子组件分割策略:较重的状态组件适合拆分
  9. SSR 服务端渲染 解决首屏渲染慢的问题

6. 刷新后 Vuex 状态丢失怎么解决?

思路:

  1. 刷新后 Vuex 状态为什么会丢失?
  2. 解决方法
  3. 第三方库以及原理探讨
  4. 个人理解

回答:

  1. 因为 Vuex 只是在内存中保存状态,刷新后就会丢失,如果要持久化就要存起来。
  2. 可以是用 localStorage 存储 Vuex 的状态,store 中把值取出来作为 state 的初始值,提交 mutation 的时候就存入 localStorage
  3. 可以用 vuex-persistvuex-persistedstate 这种插件,可以通过插件选项控制哪些需要持久化。内部的原理就是通过订阅 mutation 变化做统一处理。
  4. 这里有两个问题,一是如果用户手动改了 localStorage怎么办?那我 Vuex 里的状态不是也改变了?二是由于 localStorage API 的原因只能存储字符串,所以我们只能将数据通过 JSON.stringify 转换为字符串,而当我们存储的数据为 MapSetFunction 这种引用类型的数据时,JSON.stringify 转换后会变味 {} 而丢失。

对应第一个问题我的解决方法是可以通过 监听 storage 事件来清除数据

window.addEventListener("storage", function () {
    localStorage.clear();
    window.location.href = '/login'
    console.error("不要修改localStorage的值~~~");
});
复制代码

对于第二个问题没办法了,只能选择不适用 MapSet 这种引用类型。

7. Vue3 为什么用 Proxy 替代 defineProperty ?

思路:

  1. 属性拦截的几种方式
  2. defineProperty的问题
  3. Proxy的优点
  4. 其他考量

回答:

  1. JS 中做属性拦截常见的方式有三种:definePropertygetter/settersProxy
  2. Vue2 中使用 defineProperty 的原因是, 2013 年只能使用这种方式,由于该 API 存在一些局限性,比如对于数组的拦截有问题,为此 Vue 需要专门为数组响应式做一套实现。另外不能拦截那些新增、删除属性;最后 defineProperty 方案在初始化时需要深度递归遍历处理对象才能对它进行完全拦截,明显增加了初始化的时间。
  3. 以上两点在 Proxy 出现后迎刃而解,不仅可以对数组实现拦截,还能对 MapSet 实现拦截;另外 Proxy 的拦截也是懒处理行为,如果用户没有访问嵌套对象,那么也不会实施拦截,这就让初始化的速度和内存占用改善了。
  4. Proxy 有兼容性问题,完全不支持IE

8. 怎么实现路由懒加载?

思路:

  1. 必要性
  2. 何时用
  3. 怎么用
  4. 使用细节

回答:

  1. 当打包构建时,Javascript 抱回变得非常大,影响页面加载。利用路由懒加载我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应最贱,这样更加高效,是一种优化手段。
  2. 一般来说,对于所有的路由都使用动态导入是个好主意
  3. component 选项配置一个返回 Promise组件的函数就可以定义懒加载路由.例如:
{
  path: '/login',
  component: () => import('../views/login/Login.vue')
},
复制代码
  1. 结合注释
{
  path: '/login',
  component: () => import(/* webpackChunkName: "login" */'../views/login/Login.vue')
},
复制代码

vite中结合rollupOptions定义分块 5. 路由中不能使用异步组件

9. history模式 和 hash 模式有何区别?

  1. Vue-Router 有三个模式,其中 history 和 hash 更为常用。两者差别主要在显示形式和部署上,
  2. hash模式在地址栏现实的时候有一个 #,这种方式使用和部署都较简单;history模式url看起来更优雅没关,但是应用在部署时需要做特殊配置,web服务器需要做回退处理,否则会出现刷新页面404的问题。
  3. 在实现上 hash模式是监听hashchange事件触发路由跳转,history模式是监听popstate 事件触发路由跳转。

10. 说说 nextTick 的使用和原理?

  1. VuenextTick 是等待下一次 DOM 更新刷新的工具方法。
  2. Vue 有一个异步更新策略,意思是如果数据变化,Vue 不会立刻更新 DOM,而是开启一个队列,把组件更新函数保存在队列中,在同一时间循环中发生的所有数据变更会异步的批量更新。这一策略导致我们对数据的修改不会立刻体现在 DOM 上,此时如果想要获取更新后的 DOM 状态,就需要使用 nextTicknextTick 接受一个函数,我们可以在这个函数内部访问最新的 DOM 状态 在开发时,有两个场景我们会用到 nextTick
  • created 中想要获取 DOM;
  • 响应式数据变化后获取 DOM 更新后的状态;
  1. nextTick 的原理:在 Vue 内部,nextTick 之所以能够让我们看到 DOM 更新后的结果,是因为我们传入的 callback 会被添加到队列刷新函数的后面,这样等队列内部的更新函数都执行完毕,所有 DOM 操作也就结束了,callback 自然能够获取最新的 DOM 值。

11. v-for 和 v-if 优先级

先回答答案:vue2 中, v-for 的优先级更高 但是在 vue3 中, v-if 的优先级更高

拓展: 无论什么时候,我们都不应该把 v-forv-if 放在一起, 怎么解决呢?一是可以定义一个计算属性,让 v-for 遍历计算属性。二是可以把 if 移到内部容器里(ulol)或者把v-for移植外部容器(template)中

vue2文档vue3文档

12. 如何监听 Vuex 状态变化?

  1. watch
  2. store.subscribe()

watch 方式,可以以字符串形式监听 $store.state.xx; subscribe 方法参数是一个回调函数,回调函数接受mutation 对象和 state 对象,可以通过 mutation.type 判断监听的目标。 wtach 方法更简单好用, subscribe 会略繁琐,一般用 vuex 插件中(可以提一下vuex的持久化插件vuex-persistvuex-persistedstate

13. 你觉得 Vuex 有什么缺点?

  1. 不支持持久化,页面刷新状态就会丢失
  2. 使用模块比较繁琐
  3. 不支持 ts (或者说很不友好)

vue3 + pinia 会是更好的组合。

14. ref 和 reactive 异同点?

  1. 两者都能返回响应式对象,ref 返回的是一个响应式Ref 对象, reactive 返回的是响应式代理对象。
  2. ref 通常是处理单值得响应式,reactive 用于处理对象类型的数据响应式
  3. ref 需要通过 .value 访问, 在视图中会自动脱 ref,不需要 .valueref 可以接收对象或数组但内部依然是 reactive 实现的;reactive 如果接收 Ref 对象会自动脱 ref ;使用展开运算符展开 reactive 返回的响应式对象会使其失去响应性,可以结合 toRefs()将值转换为 Ref 对象后再展开。
  4. reactive 内部使用 Prxoy 代理拦截对象各种操作,而 ref 内部封装一个 RefImpl 类,设置 get value/set value,拦截用户对值得访问。

16. Vue 中如何扩展一个组件?

  1. 逻辑扩展:mixinsextendscomposition api:
  2. 内容扩展:slots

mixins 很灵活,但是会冲突很混乱。extends 是一个不太常用的选项,更 mixins 的不同是它只能扩展单个对象,优先级比 mixins 高。

混入的数据和方法 不能明确判断来源 而且可能和当前组件内变量 产生命名冲突,composition api 可以很好解决这些问题,利用独立出来的响应式模块可以很方便的编写独立逻辑并提供响应式数据局,增强代码的可读性和维护性。

扩展:Vue.mixin(全局混入) Vue.extend(有点像是 类/组件的继承 创建一个子类)

17. vue-loader 是什么?

  1. vue-loader 是用于处理单文件组件(SFC)的webpack loader
  2. 因为有了 vue-loader,我们才能用 .vue 文件形式编写代码,将代码分割为 templatescriptstyle
  3. webpack 在打包的时候,会以 loader 的方式调用 vue-loader
  4. vue-loader 被执行时,它会对 SFC 中的每个语言块用单独的 loader 链处理,最后将这些单独的块装配成最终的组件模块

18. 子组件能否修改父组件数据

不能直接改。

组件化开发中有一个单向数据流原则,不在子组件修改父组件数据是个常识

如果你确实需要改,请通过emit向父组件发送一个事件,在父组件中修改

19. 怎么定义动态路由,怎么获取传过来的动态参数?

我么可以在路径中使用一个动态字段来实现,例如/users/:id 其中 :id 就是路径参数。 可以通过 this.$route.parmas获取,参数还可以有多个, $route 对象还公开了其他有用的信息如 queryhash等。

Vue 面试题汇总(二):https://developer.aliyun.com/article/1414950

相关文章
|
4月前
|
JavaScript 前端开发 应用服务中间件
【Vue面试题三十】、vue项目本地开发完成后部署到服务器后报404是什么原因呢?
这篇文章分析了Vue项目在服务器部署后出现404错误的原因,主要是由于history路由模式下服务器缺少对单页应用的支持,并提供了通过修改nginx配置使用`try_files`指令重定向所有请求到`index.html`的解决方案。
【Vue面试题三十】、vue项目本地开发完成后部署到服务器后报404是什么原因呢?
|
4月前
|
JavaScript
【Vue面试题十五】、说说你对slot的理解?slot使用场景有哪些?
这篇文章深入探讨了Vue中的`slot`概念,包括它的定义、使用场景和分类(默认插槽、具名插槽和作用域插槽),并通过代码示例展示了如何在组件中使用插槽来实现内容的分发和自定义。同时,文章还对插槽的工作原理进行了分析,解释了`renderSlot`函数和`$scopedSlots`对象的角色。
【Vue面试题十五】、说说你对slot的理解?slot使用场景有哪些?
|
4月前
|
JavaScript 前端开发
【Vue面试题二十五】、你了解axios的原理吗?有看过它的源码吗?
这篇文章主要讨论了axios的使用、原理以及源码分析。 文章中首先回顾了axios的基本用法,包括发送请求、请求拦截器和响应拦截器的使用,以及如何取消请求。接着,作者实现了一个简易版的axios,包括构造函数、请求方法、拦截器的实现等。最后,文章对axios的源码进行了分析,包括目录结构、核心文件axios.js的内容,以及axios实例化过程中的配置合并、拦截器的使用等。
【Vue面试题二十五】、你了解axios的原理吗?有看过它的源码吗?
|
4月前
|
JavaScript 前端开发 数据处理
【Vue面试题二十八】、vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?
这篇文章讨论了Vue中实现权限管理的策略,包括接口权限、路由权限、菜单权限和按钮权限的控制方法,并提供了不同的实现方案及代码示例,以确保用户只能访问被授权的资源。
【Vue面试题二十八】、vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?
|
4月前
|
JavaScript 前端开发
【Vue面试题二十七】、你了解axios的原理吗?有看过它的源码吗?
文章讨论了Vue项目目录结构的设计原则和实践,强调了项目结构清晰的重要性,提出了包括语义一致性、单一入口/出口、就近原则、公共文件的绝对路径引用等原则,并展示了单页面和多页面Vue项目的目录结构示例。
|
3月前
|
缓存 JavaScript 前端开发
vue面试题
vue面试题
173 64
|
2月前
|
JavaScript 前端开发
vue尚品汇商城项目-day01【8.路由跳转与传参相关面试题】
vue尚品汇商城项目-day01【8.路由跳转与传参相关面试题】
43 0
vue尚品汇商城项目-day01【8.路由跳转与传参相关面试题】
|
4月前
|
JavaScript 安全 前端开发
【Vue面试题二十九】、Vue项目中你是如何解决跨域的呢?
这篇文章介绍了Vue项目中解决跨域问题的方法,包括使用CORS设置HTTP头、通过Proxy代理服务器进行请求转发,以及在vue.config.js中配置代理对象的策略。
【Vue面试题二十九】、Vue项目中你是如何解决跨域的呢?
|
4月前
|
JavaScript 前端开发 编译器
【Vue面试题三十二】、vue3有了解过吗?能说说跟vue2的区别吗?
这篇文章介绍了Vue 3相对于Vue 2的改进和新增特性,包括性能提升、体积减小、更易维护、更好的TypeScript支持、新的Composition API、新增的Teleport和createRenderer功能,以及Vue 3中的非兼容性变更和API的移除或重命名。
【Vue面试题三十二】、vue3有了解过吗?能说说跟vue2的区别吗?
|
4月前
|
JavaScript 前端开发 API
【Vue面试题三十一】、你是怎么处理vue项目中的错误的?
这篇文章讨论了Vue项目中错误的处理方式,包括后端接口错误和代码逻辑错误的处理策略。文章详细介绍了如何使用axios的拦截器处理后端接口错误,以及Vue提供的全局错误处理函数`errorHandler`和生命周期钩子`errorCaptured`来处理代码中的逻辑错误。此外,还分析了Vue错误处理的源码,解释了`handleError`、`globalHandleError`、`invokeWithErrorHandling`和`logError`函数的作用和处理流程。
【Vue面试题三十一】、你是怎么处理vue项目中的错误的?