面试笔记

65 阅读10分钟

问题1:谈谈MVVM的理解

MVVM(Model-View-ViewModel)是一种软件架构设计模式,而 Vue.js 是一个基于 MVVM 思想的前端框架。可以说,Vue.js 实现了 MVVM 的思想,借此为开发者提供了更清晰、简洁的代码结构和更高效的开发体验。

MVVM 是一种设计模式,用于构建用户界面,特别是在 UI 和数据之间的双向绑定(数据驱动视图)方面,显著提高了前端开发的效率。MVVM 将应用分为三层:

  • Model(模型) :表示应用程序的底层数据和业务逻辑,它是纯粹的数据来源。模型与业务逻辑和数据库交互,不直接与用户界面打交道。
  • View(视图) :用户看到并与之交互的界面。它是 HTML、CSS 构成的网页,负责呈现数据和接收用户操作。
  • ViewModel(视图模型) :是 Model 和 View 之间的桥梁。它包含了处理数据的逻辑,响应用户的交互,把用户界面的变更反映到模型上,同时把模型的数据映射到视图中。

通过使用 MVVM,视图(View)和数据(Model)被解耦,开发者可以将更多精力集中在逻辑实现上,而不需要频繁操心手动更新视图。

问题2:说说的vue的生命周期

在 Vue.js 中,生命周期是指从组件创建、挂载、更新到销毁的整个过程。Vue 提供了一些生命周期钩子函数(生命周期函数),允许开发者在组件的不同阶段执行特定的代码。

Vue 组件的生命周期可以分为四个主要阶段:创建阶段挂载阶段更新阶段销毁阶段。每个阶段都有相应的生命周期钩子,下面是对这些生命周期钩子函数的详细描述:

1. 创建阶段

在组件实例被创建并初始化时,首先会执行一些创建阶段的生命周期钩子。这些钩子主要用于初始化数据、侦听器、计算属性等,但此时还没有与 DOM 建立联系,页面上还看不到内容。

  • beforeCreate

    • 触发时机:实例初始化之后,数据观察和事件尚未配置。
    • 用途:在这个阶段还无法访问 datamethods 等,因为它们还没有被初始化。
  • created``创建

    • 触发时机:实例创建完成,datamethodscomputedwatch 都已初始化,但尚未挂载到 DOM。
    • 用途:可以在此处进行数据获取操作(例如异步请求),此时已经可以访问组件的数据和方法,但组件还没有插入到页面上。

2. 挂载阶段

在组件的模板已经编译完成并准备挂载到真实的 DOM 上时,会经历挂载阶段的生命周期钩子。

  • beforeMount

    • 触发时机:在挂载开始之前被调用,此时虚拟 DOM 已经创建完成,但还没有生成实际的 DOM。
    • 用途:可以在这里进行一些在挂载前的最后调整。
  • mounted 安装

    • 触发时机:组件挂载到 DOM 上之后被调用,此时已经可以访问 DOM 元素。
    • 用途:一般用于操作 DOM、启动定时器、获取页面上的 DOM 元素等。

3. 更新阶段

当组件的数据发生变化时,Vue 会进入更新阶段。更新阶段的钩子函数会在数据变动重新渲染之前和之后触发。

  • beforeUpdate``beforeUpdate 更新

    • 触发时机:数据变化导致组件需要重新渲染之前被调用。
    • 用途:可以在更新前访问更新前的 DOM 状态,可以用于保存状态等操作。
  • updated 更新

    • 触发时机:由于数据变化,组件重新渲染并更新 DOM 之后被调用。
    • 用途:可以在更新完成后对 DOM 做一些操作,比如依赖 DOM 的操作,但请避免直接修改数据,这样可能会导致无限循环更新。

4. 销毁阶段

当组件不再需要时,Vue 会销毁组件实例,这时会进入销毁阶段。销毁阶段的钩子函数用于进行一些清理工作,比如清除定时器、移除事件监听等。

  • beforeDestroy

    • 触发时机:实例销毁之前调用,此时实例仍然是完全可用的。
    • 用途:可以在这里执行一些销毁前的清理工作,比如移除事件监听器或清除定时器。
  • destroyed 摧毁

    • 触发时机:实例销毁之后调用,组件的所有绑定、事件和子实例都会被销毁。
    • 用途:此时组件已经从 DOM 中移除,所有数据和事件监听器均无效,一般用于彻底的清理。

问题3:v-for中的key关键字有什么作用

在 Vue.js 中,v-for 指令用于渲染列表数据,而在使用 v-for 时,通常需要添加 key 属性。key 属性在 Vue 的虚拟 DOM (Virtual DOM) 中扮演着重要的角色,确保高效和正确的渲染。以下是 key 的具体作用和必要性:

1. 唯一标识每个元素,提升渲染性能

key 用于唯一标识每个列表元素,帮助 Vue 区分各个元素。在使用 v-for 渲染列表时,当数据发生变化时,Vue 需要通过比较新的列表与旧的列表来确定哪些元素发生了变化,从而高效地更新 DOM。如果没有 key,Vue 在更新列表时会采用一种“默认复用”的策略来对比和更新元素,这可能导致某些元素被错误地复用或更新。

  • 使用 key 可以优化 Diff 算法的性能:Vue 在进行虚拟 DOM diff 操作时,如果没有 key,它会按顺序比较每个元素,这种方式效率较低。而使用 key 后,Vue 可以根据 key 值快速找到对应的元素,从而减少不必要的 DOM 操作,提升渲染性能。

2. 确保元素的稳定性和一致性

key 还用于确保在渲染或重新排序时,元素的状态能得到正确的维护。例如,在表单元素的输入框中,如果没有 key,当数组元素的顺序发生变化时,Vue 可能会错误地保留输入框的内容,而导致数据错乱。

  • 避免副作用:如果 key 没有唯一标识,或者直接使用数组索引作为 key,当数据发生重新排序时,Vue 可能会复用错误的元素,导致状态混乱。例如,如果有两个输入框,交换它们的顺序时,没有唯一的 key 会导致输入框中的内容也被错误地交换,从而导致用户体验问题。

3. key 必须是唯一且稳定的值

  • 唯一性key 必须在同级元素中是唯一的,这样 Vue 才能正确地追踪每一个元素。
  • 稳定性key 还必须是稳定的,这意味着它不能是一个会随时间变化的值,否则每次更新时 Vue 都会认为它是不同的元素,导致不必要的重新渲染。

key 使用的最佳实践

  • 使用 唯一标识符:比如数组元素中的 id 属性。
  • 避免使用 数组索引 作为 key:虽然可以使用索引,但在某些情况下会产生副作用,例如对数据进行增删操作时,索引可能会改变,导致元素复用错误,影响用户体验。因此,推荐使用唯一且不会变动的标识符(如数据库中的 id)作为 key

问题4:Vue中父组件和子组件的数据传递

1. 父组件向子组件传递数据 (props)

父组件可以通过 props 将数据传递给子组件,子组件则通过接收 props 的方式来访问父组件传递的数据。

  • 父组件使用 props 向子组件传递数据

    • 在父组件中,通过自定义属性的形式为子组件传递数据。
    • 子组件通过声明 props 来接收这些数据。

2. 子组件向父组件传递数据 ($emit)

子组件可以通过 事件 的方式将数据传递给父组件。具体实现是子组件在需要传递数据时,通过 $emit 触发一个自定义事件,父组件在使用子组件时监听这个自定义事件,从而获取子组件传递的数据。

  • 子组件通过 $emit 触发事件传递数据
  • 父组件通过监听子组件的自定义事件接收数据

3. 使用 v-model 在父子组件之间进行双向绑定

Vue 还允许通过 v-model 实现父组件和子组件之间的双向绑定。这种方式多用于表单组件,父组件可以使用 v-model 绑定一个值,子组件接收并且可以修改这个值,从而实现双向数据传递。

4. 使用事件总线 (Event Bus) 或 Vuex

在一些复杂的场景中,特别是当需要在多个组件之间共享数据时,可以使用 事件总线 (Event Bus)Vuex 状态管理。

  • 事件总线:通过创建一个 Vue 实例来充当事件总线,将其导入到需要通信的父子组件中,实现任意组件之间的通信。
  • Vuex:对于全局共享的数据,可以使用 Vuex 来管理状态,从而方便不同组件之间的数据同步。

总结

  • 父组件向子组件传递数据:使用 props
  • 子组件向父组件传递数据:使用 $emit 触发事件。
  • 双向数据绑定:使用 v-model 绑定值。
  • 复杂场景下的全局数据共享:使用事件总线 (Event Bus) 或 Vuex。

问题5:v-if和v-show的区别

在 Vue 中,v-ifv-show 都可以用来控制元素的显示和隐藏,但它们在实现机制和使用场景上有明显的区别:

1. 实现机制

  • **v-if**中:

    • 真正的条件渲染。当条件为 false 时,元素不会被渲染到 DOM 中,完全从 DOM 树中移除。当条件变为 true 时,Vue 会将元素重新插入 DOM 中。
    • 动态渲染:元素的添加和移除涉及对 DOM 的创建和销毁,因此会有更高的性能开销,尤其是在频繁切换时。
  • **v-show**中:

    • 通过 CSS 控制显示。无论条件是 true 还是 false,元素都会一直被渲染到 DOM 中。v-show 的作用是通过修改元素的 CSS display 属性来控制显示和隐藏。
    • 静态渲染:因为元素始终在 DOM 中,v-show 只是简单地切换 display 属性,所以切换的性能开销更小。

2. 使用场景

  • v-if 中:

    • 适用于元素的 条件性渲染。当某个元素的渲染非常少见(例如只在特定情况下渲染一次),v-if 更合适,因为它可以避免不必要的 DOM 操作。
    • 因为 v-if 会真正地移除或添加元素到 DOM 中,因此在初次加载时延迟渲染也是一个优势。
  • v-show 中:

    • 适用于需要 频繁切换显示和隐藏 的场景。例如,元素在不同条件下反复显示和隐藏,使用 v-show 可以降低性能消耗,因为它不会涉及 DOM 的销毁和创建。
    • 元素始终在 DOM 中,只是 display 切换,因此切换速度更快。

3. 性能对比

  • v-if 中:

    • 高开销:每次条件变化时,元素都会被添加或删除。因此,对于需要频繁切换的内容来说,性能开销较高。
    • 适合条件性渲染:但在初次加载时不渲染元素的场景下,v-if 是更合适的选择,因为它不会浪费初次渲染的资源。
  • v-show 中:

    • 低开销:只是修改了元素的 display 样式,因此对于频繁切换的场景开销较低。
    • 内存占用:但是由于元素始终在 DOM 中,如果是大量元素的话,可能会带来内存占用的问题。

问题6:Vue Router的跳转方法

  • <router-link> :适用于模板中的链接跳转,类似于 HTML 中的 <a> 标签。

  • this.$router.push() :用于编程式导航,添加新的历史记录。

  • this.$router.replace() :用于编程式导航,不添加新的历史记录,而是替换当前记录。

  • this.$router.go() :用于前进或后退指定步数,类似于浏览器的导航操作

问题7:Element UI 的特点

  1. 丰富的组件库

    • Element UI 提供了一系列常用的 UI 组件,如按钮、表单、对话框、表格、树形结构、卡片、布局等,基本涵盖了常见的开发需求。
  2. 开箱即用

    • 每个组件都经过设计和优化,可以直接在项目中使用,减少了开发人员设计和调整 UI 的时间。每个组件的样式和功能都是一致的,这对于大型项目中的统一风格非常重要。
  3. 适合中后台开发

    • Element UI 尤其适合用于开发企业级管理后台系统,提供了诸如数据表格、分页、导航菜单、对话框、树形结构等适合后台系统的功能。
  4. 易于定制

    • 组件库允许根据项目的需要定制主题,可以通过修改 SCSS 变量来定制组件样式,使其更符合项目的品牌要求。