前端面试问题汇总 - Vue篇

1. Vue 的生命周期有哪些,每个阶段分别做什么操作?

  • beforeCreate:
    • 在实例初始化之后、数据观测和事件配置之前被调用。
    • 此时数据对象 data 和事件(methods)都还未初始化。
    • 一般不在此阶段进行数据初始化和 DOM 操作。
  • created:
    • 在实例创建完成后被立即调用。
    • 实例已完成数据观测、属性和方法的运算,但尚未挂载到 DOM 上。
    • 可以进行异步操作、数据初始化以及监听数据的变化等操作。
  • beforeMount:
    • 在挂载开始之前被调用:相关的 render 函数首次被调用。
    • 在此阶段,模板编译已完成,但尚未将生成的 DOM 插入页面。
  • mounted:
    • 在挂载完成后被调用。
    • 在此阶段,组件已经被挂载到页面中,DOM 元素已经生成,可以进行 DOM 操作、访问 DOM 元素、发送网络请求等。
  • beforeUpdate:
    • 在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。
    • 在此阶段,数据已经更新,但是尚未重新渲染到视图中。
  • updated:
    • 在数据更新之后被调用,发生在虚拟 DOM 重新渲染和打补丁之后。
    • 在此阶段,组件的 DOM 已经更新,可以进行一些操作,如数据同步、手动修改 DOM 等。
  • beforeDestroy:
    • 在实例销毁之前调用。在这一步,实例仍然完全可用。
    • 可以在这里进行清理工作,比如取消定时器、清除非 Vue.js 的事件监听器等。
  • destroyed:
    • 在实例销毁之后调用。在这一步,所有的事件监听器和子实例被移除。
    • 在此阶段,组件已经被销毁,数据绑定和监听被清除,但 DOM 元素还存在。

2. Vue组件通信方式有哪些?

  • Props 和 Events: 父组件通过 props 向子组件传递数据,子组件通过 events 向父组件发送消息。这是最基本和常见的组件通信方式。
  • 自定义事件: 使用 Vue 的 $emit() 方法在子组件中触发自定义事件,然后在父组件中监听并处理这些事件。
  • 事件总线(Event Bus): 创建一个全局的 Vue 实例作为事件总线,通过这个实例来触发和监听事件,不管组件的层级关系如何都可以进行通信。
  • Vuex 状态管理: 对于大型应用程序,使用 Vuex 可以更方便地管理组件之间共享的状态。Vuex 提供了集中式存储管理,并提供了一些额外的 API 来实现组件之间的通信。
  • $refs: 在父组件中通过 $refs 来访问子组件的实例,从而直接调用子组件的方法或访问子组件的数据。
  • Provide 和 Inject: 祖先组件通过 provide 来提供数据,然后后代组件通过 inject 来注入提供的数据。这种方式可以跨越多层级的组件进行通信。
  • $attrs 和 listeners: 父组件可以通过 v-bind="attrs" 将所有属性传递给子组件,通过 v-on="$listeners" 将所有监听器传递给子组件,从而实现透传属性和事件的目的。
  • $parent 和 $children: 在某些情况下,您可以直接通过 $parent 或 $children 访问父组件或子组件的实例,以实现通信。

3. Vuex 的核心属性及作用?

  • State(状态): Vuex 的核心是一个存储中心,称为状态(State),它包含了应用中所有组件的共享数据。可以将 Vuex 的状态想象为应用的单一数据源,组件中的数据都应该从这个状态中获取。
  • Getters(获取器): Getters 允许我们在 Vuex 的状态上进行计算操作,并且可以派生出一些新的状态。它类似于 Vue 组件中的计算属性,可以在获取数据时进行一些逻辑处理。
  • Mutations(突变): Mutations 是用来修改 Vuex 的状态的方法。它们是同步的,每个 Mutation 都有一个字符串类型的事件类型和一个回调函数,用于修改状态。
  • Actions(动作): Actions 类似于 Mutations,不同之处在于 Actions 提交的是 Mutation 而不是直接变更状态,可以包含任意异步操作。它们是用于处理业务逻辑的地方,例如处理异步请求、封装多个 Mutation 等。
  • Modules(模块): Vuex 允许将 Store 分割成模块(Modules),每个模块拥有自己的 State、Getters、Mutations 和 Actions,可以更好地组织代码和管理复杂的状态。

4. Vue 的监听属性和计算属性的区别?

监听属性用于监视 Vue 实例上的数据变化,并在数据变化时执行一些自定义的操作。当需要在数据发生变化时执行异步或复杂的操作时,通常会使用监听属性。监听属性是一个对象,其属性是要监听的数据,值是一个函数,用于处理数据变化时的逻辑。

计算属性用于基于已有的数据衍生出新的数据,并且只有在相关依赖发生改变时才会重新计算。计算属性是一个函数,在 Vue 实例中使用 computed 选项来定义。计算属性会缓存计算结果,只有在相关依赖发生改变时才会重新计算,并且在多次访问时只会计算一次。

区别如下:

  • 响应性: 计算属性具有缓存机制,只有在依赖的数据发生变化时才会重新计算,而监听属性没有缓存机制,每次数据变化都会触发监听函数。
  • 用法: 计算属性适用于基于已有数据衍生出新的数据,而监听属性适用于需要在数据变化时执行异步或复杂的操作。
  • 语法: 计算属性是一个函数,而监听属性是一个对象,其属性是要监听的数据,值是一个处理函数。

5. Vue的导航守卫有哪一些?

导航守卫是一组用于控制路由导航的钩子函数,允许您在路由发生变化时执行一些逻辑。Vue Router 提供了多种导航守卫,包括全局导航守卫、路由独享的守卫和组件内的守卫。

Vue Router 中常用的导航守卫:

  • 全局守卫
    • beforeEach: 在路由切换开始时执行,常用于进行全局的身份验证、权限验证、路由跳转等操作。
    • beforeResolve: 在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后执行。这个守卫不会等待异步路由组件解析完成就立即执行,适合在确保所有异步组件都被解析完毕后执行一些逻辑。
    • afterEach: 在导航完成后(即在所有组件渲染完成后)执行,常用于页面统计、日志记录等操作。
  • 路由独享的守卫
    • beforeEnter: 在路由配置中直接定义的导航守卫,仅在特定路由上生效。
  • 组件内的守卫:
    • beforeRouteEnter: 在路由进入该组件前执行,可以访问不到组件实例 this,但可以通过回调函数访问到组件实例。
    • beforeRouteUpdate: 在当前路由改变,但是该组件被复用时执行,常用于同一组件不同参数间的切换。
    • beforeRouteLeave: 在导航离开该组件的对应路由时执行,常用于在用户离开当前页面前进行确认操作或保存未提交的数据。

6. Vue2 与 Vue3 有什么区别?

  • 性能优化:Vue 3 在性能方面进行了大幅优化,包括虚拟 DOM 的重写、编译器的升级、组件实例的优化等,使得 Vue 3 在渲染速度和内存占用方面都有明显的提升。
  • Composition API:Vue 3 引入了 Composition API,它是一种新的组件 API 设计,提供了更灵活、更可复用的组件逻辑组织方式,使得组件逻辑更清晰、更易于维护。
  • 响应式系统的改进:Vue 3 中的响应式系统经过了重构和优化,使用了 Proxy 来代替 Object.defineProperty,提供了更好的性能和更完整的类型推断。
  • TypeScript 支持:Vue 3 对 TypeScript 的支持更加完善,包括更好的类型推断、更全面的类型定义等,使得使用 TypeScript 开发 Vue 应用更加便捷。
  • 静态提升和 Tree-shaking:Vue 3 改进了静态提升和 Tree-shaking,使得打包出的代码更小、更高效,同时也提高了应用的性能。
  • Teleport 和 Suspense:Vue 3 引入了 Teleport 组件和 Suspense 组件,用于更灵活地控制组件的挂载位置和处理异步组件加载时的 loading 状态。
  • Fragment 和 Portal:Vue 3 支持 Fragment 和 Portal,允许开发者更灵活地组织组件的结构和布局。
  • 性能警告:Vue 3 引入了性能警告,在开发模式下,如果发现组件渲染存在性能问题,会在控制台给出警告,帮助开发者优化代码。

7. Vue常用指令有哪些?

  • v-bind: 用于动态绑定 HTML 属性,可以简写为 :
  • v-model: 用于实现表单元素和应用程序状态之间的双向数据绑定,常用于表单输入元素
  • v-if / v-else: 用于根据表达式的真假条件来条件性地渲染元素,v-else 表示否定条件
  • v-show: 类似于 v-if,但是使用 CSS 的 display 属性来控制元素的显示和隐藏,而不是直接添加和移除元素
  • v-for: 用于遍历数组或对象,生成重复的 HTML 元素
  • v-on: 用于监听 DOM 事件,执行相应的 JavaScript 代码,可以简写为 @
  • v-pre: 跳过该元素和其子元素的编译过程,用于优化渲染性能
  • v-cloak: 用于在 Vue 实例加载之前隐藏未编译的 Mustache 标签,避免页面闪烁
  • v-text / v-html: 分别用于替代元素的 textContent 和 innerHTML 属性,用于动态设置元素的文本内容或 HTML 内容
  • v-once: 只渲染元素和组件一次,不会随着数据的变化重新渲染
  • v-slot: 用于命名插槽和作用域插槽的语法,用于更灵活地定义组件的内容分发

8. v-if 和 v-show 有什么区别?

v-if值为false时,会销毁元素,而v-show则仅是通过display来控制元素的显示和隐藏。

v-if 适用于需要对性能进行优化的场景,因为它可以避免不必要的 DOM 渲染和事件监听;v-show适用于对性能要求不高,但需要频繁切换显示和隐藏的场景。

9. v-for为什么要加一个key?

在使用 v-for 指令对数组或对象进行循环渲染时,通常需要为每个遍历的元素添加一个唯一的 key 属性。这是因为 Vue.js 在进行列表渲染时,会尽可能地高效更新 DOM,以减少不必要的 DOM 操作。而使用 key 属性可以帮助 Vue.js 进行有效的列表渲染和更新。

10. keep-alive是什么?有哪几个生命周期阶段?

<keep-alive> 是 Vue.js 提供的一个抽象组件,用于将动态组件缓存到内存中,以便在组件切换时保留其状态或避免重新渲染。当一个包裹在 <keep-alive> 内的动态组件被切换时,其状态将被保留,而不会被销毁和重新创建,以提高性能和用户体验。

生命周期:

  • activated: 在被包裹的动态组件被激活时调用。这意味着组件被缓存并且再次被显示出来。例如,当组件从 <keep-alive> 缓存中被加载出来时。
  • deactivated: 在被包裹的动态组件被停用时调用。这意味着组件被缓存但不再被显示。例如,当组件被切换出去并被缓存起来时。

11. EventBus是什么东西?

EventBus(事件总线)是一种设计模式,用于在应用程序的不同组件之间进行通信。它允许组件在不直接相互引用的情况下进行通信,从而提高了组件之间的解耦性。

在 Vue.js 中,EventBus 是一个 Vue 实例,可以用于在组件之间发送和接收事件。通常情况下,我们可以通过在 Vue 原型上添加一个新的 Vue 实例来创建 EventBus,然后在组件中通过该实例来发送和监听事件。

12. 父子组件生命周期执行顺序是怎么样的?

  1. beforeCreate
  2. created
  3. beforeMount
  4. 子组件的 beforeCreate
  5. 子组件的 created
  6. 子组件的 beforeMount
  7. 子组件的 mounted
  8. mounted

13. Vue的双向绑定原理是什么,关键点在哪里?

  • 数据劫持(响应式系统): Vue 使用了 Object.defineProperty() 方法来劫持(或监听)数据的属性,当数据发生变化时,可以通知相关的视图更新。这个过程是在 Vue 实例化阶段进行的,即在 Vue() 函数内部进行。
  • 虚拟 DOM: Vue 使用虚拟 DOM 来描述视图,当数据发生变化时,Vue 会通过比较新旧虚拟 DOM 树的差异,最小化地更新实际 DOM,以提高性能。
  • 模板编译: 在 Vue 模板编译过程中,会将模板转换成渲染函数(render function),这个渲染函数返回的是一个 VNode(虚拟节点)树,描述了视图的结构和内容。
  • 发布-订阅模式: Vue 使用了发布-订阅模式来实现数据的响应式更新。当数据发生变化时,会通知相关的订阅者(观察者),从而触发相应的更新操作。这个过程是在数据劫持过程中实现的,即当属性的 getter 或 setter 被访问或修改时触发。
  • 双向绑定: 双向绑定是指数据的变化可以影响视图的更新,同时视图的变化也可以影响数据的更新。在 Vue 中,通过 v-model 指令可以实现表单元素和数据的双向绑定,当表单元素的值发生变化时,会更新数据,反之亦然。

14. vue3为什么要用proxy替代defineProperty?

  • 更全面的拦截功能: Proxy 提供了更多的拦截器,比 Object.defineProperty 更加灵活,可以拦截更多类型的操作,包括对象的删除、添加、枚举等。
  • 更好的性能: 在特定情况下,使用 Proxy 可以比 Object.defineProperty 更高效。在 Vue 3 中,Vue 使用了基于 Proxy 的响应式系统,在大多数情况下,性能优于 Vue 2 中基于 Object.defineProperty 的实现。
  • 避免了一些限制: 使用 Proxy 可以避免 Object.defineProperty 的一些限制,比如不能监视数组的变化、不能监视动态添加的属性等问题。
  • 更好的 TypeScript 支持: Proxy 对 TypeScript 的支持更加友好,可以更准确地推断类型和提供类型安全。
  • 更易于维护和扩展: Proxy 提供了更清晰和直观的 API,使代码更易于理解和维护,并且更容易进行扩展和定制。

15. Vue有哪些钩子,如何自定义钩子?

  • beforeCreate: 在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
  • created: 在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
  • beforeMount: 在挂载开始之前被调用:相关的 render 函数首次被调用。
  • mounted: el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
  • beforeUpdate: 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
  • updated: 由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用。

beforeUnmount (Vue 2.x) / beforeUnmount (Vue 3.x): 在卸载组件之前调用。

  • unmounted: 组件被卸载后调用。
  • errorCaptured: 捕获子孙组件的错误。工作方式类似于全局错误处理器。

要自定义钩子,您可以使用 Vue.mixin() 方法或编写全局插件。例如,使用 mixin 可以这样自定义一个钩子:

复制代码
Vue.mixin({`
  `created:` `function` `()` `{`
    `// 任意自定义逻辑`
`    console.log('Custom created hook');`
  `}`
`});

16. Vue中的mixin

在 Vue 中,Mixin 是一种可复用的组件选项对象。它允许您在多个组件中共享和重用代码,从而实现代码的复用和组件的扩展。Mixin 提供了一种在组件之间共享代码的方式,可以将一些通用的逻辑、数据和方法提取到 Mixin 中,然后将其混入到需要的组件中。

Mixin 可以包含组件选项对象中的任何选项,包括 data、methods、computed、watch、生命周期钩子等。

优势:

  • 代码重用: Mixin 允许在多个组件中共享相同的逻辑和功能,减少重复编写代码的工作量。
  • 灵活性: 可以根据需要将不同的 Mixin 组合在一起,实现不同的功能组合。
  • 解耦逻辑: 可以将一些通用的逻辑和功能抽象为 Mixin,从而使组件更加简洁和专注于自身的业务逻辑。
  • 扩展性: 可以在不修改原始组件代码的情况下,通过混入额外的 Mixin 来扩展组件的功能。

17. Vue路由模式有哪些 原理 是什么

哈希模式(Hash Mode):

  • 哈希模式是 Vue Router 的默认模式,也是较老的一种路由模式。
  • 由于哈希部分的改变不会重新加载页面,因此在单页应用中,哈希模式能够很好地支持前端路由。
  • 原理:在哈希模式中,路由信息被保存在 URL 的哈希部分(即 # 号之后),当用户点击页面内的链接时,哈希部分会改变,但浏览器不会向服务器发送请求,而是通过监听 hashchange 事件来进行路由的切换。Vue Router 会使用 window.addEventListener('hashchange', callback) 监听 hash 的改变,一旦 hash 发生变化,就会触发相应的路由切换。

历史模式(History Mode):

  • 历史模式使用 HTML5 的 History API 来管理路由状态。
  • 在历史模式中,路由信息以常规的 URL 形式显示,而不需要 # 号,看起来更加美观。
  • 历史模式下,需要服务端的支持来配置处理前端路由请求的路径。
  • 原理:当用户点击页面内的链接时,浏览器会向服务器发送请求,服务器需要配置处理前端路由请求的路径,以返回正确的页面。Vue Router 使用 History API 提供的 pushState() 和 replaceState() 方法来添加和修改历史记录,以及监听浏览器的 popstate 事件来响应历史记录的变化。
相关推荐
吕彬-前端23 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱25 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai35 分钟前
uniapp
前端·javascript·vue.js·uni-app
bysking2 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
独行soc2 小时前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205872 小时前
web端手机录音
前端