Vue相关面试重点真题汇总

266 阅读9分钟

汇总了一些相对比较新的高频、重点面试题,包含了些热门技术和知识点。回顾之前发的博文知识点,帮助大家进行知识点复习。祝大家早日能够找到理想的工作。

1、v-show和v-if的区别

  • v-show是通过CSS的display来控制隐藏或显示。
  • v-if是真正的渲染和销毁,而不是隐藏和显示。
  • 如果是频繁切换显示则使用v-show,否则用v-if

2、为何在v-for中用key

  • 首先必须用key,且key值不能是index和random
  • diff算法中通过tag和key来判断,是否是相同的节点
  • 当提供了key时,可以高效识别节点身份,避免不必要的DOM操作。

3、描述Vue组件生命周期(考虑父子组件)

Vue组件生命周期是:created(创建阶段)、mounted(渲染阶段)、updated(更新阶段)、destoryed(销毁阶段) 对于父子组件,它们的生命周期函数调用顺序是父created->子create->子mounted->父mounted->子updated->父updated->子destoryed->父destoryed 也就是说create函数是子组件会在父组件之后调用,mounted和updated函数是子组件优先父组件调用,而在子组件销毁之前,父组件的生命周期函数已经全部执行完毕。

4、Vue组件如何通讯(常见)

  • 父子组件可以用props和this.$emit
  • 自定义事件 event.onon、off $emit
  • vuex

5、描述组件渲染过程和更新过程

vue组件渲染过程包括:

(1)解析模版:Vue会将组件的模版解析成一个抽象语法树(AST),这个AST描述了模版的结构和指令等信息。

(2)创建虚拟DOM:根据AST,Vue会创建一个虚拟DOM,它是一个轻量级的Javascript对象,描述了组件的结构和属性等信息。

(3)生成真实DOM:Vue会将虚拟DOM转换成真实DOM,并插入页面中。

(4)挂载组件:组件被挂载到页面后,Vue会调用组件的生命周期函数,执行一些初始化操作。

Vue组件更新过程包括:

(1)数据更新:当组件的数据发生变化时,Vue会自动触发数据更新。

(2)重新渲染虚拟DOM:Vue会根据数据变化,重新生成虚拟DOM。

(3)更新真实DOM:Vue会将新生成的虚拟DOM与旧的虚拟DOM进行比较,找出需要更新的部分,并将其更新到真实DOM中。

(4)调用生命周期函数:更新完成后,Vue会调用组件的生命周期函数,执行一些更新后的操作。

6、双向数据绑定v-model的真实原理

Vue中的双向数据绑定实际上是一个语法糖,它是基于Vue的单项数据绑定实现的。单向数据绑定是通过数据劫持和发布-订阅模式实现的。当一个组件的数据发生变化时,Vue会自动更新相关的DOM。

具体实现原理是:

  1. 对于表单元素,Vue会监听其input或change事件,当元素的值发生变化时,会触发Vue的更新机制。
  2. 在组件的渲染过程中,Vue会为表单元素绑定一个value属性,这个属性是有数据驱动,当数据发生变化时,value数据的值也会相应的更新。
  3. 当用户修改表单元素的值时,Vue会将修改后的值赋给对应的数据属性,从而实现数据的更新。

7、对MVVM的理解

在Vue中,MVVM代表的是Model-View-ViewModel模式,它是一种前端架构模式,用于将UI逻辑与业务逻辑分离。View代表的是用户界面,ViewModel是View的抽离,Model是数据层。

MVVM模式是通过数据绑定和组件化实现的。数据绑定是指Vue将数据和DOM元素绑定在一起,当数据发生变化时,DOM元素会自动更新。组件化是指将UI界面拆分成独立的组件,每个组件都有自己的逻辑和状态,可以复用和组合。

8、computed有何特点

  • 计算属性,依赖缓存,data不变不会重新计算
  • computed的值是只读的,提高性能

9、ajax请求应该放在哪个生命周期

ajax请求通常应该放在mounted函数中。mounted是Vue实例挂载到DOM元素完成之后调用的。这个时候DOM已经渲染完成了,可以进行DOM操作了,这个时候就可以ajax请求数据了。

如果将ajax请求放在create或beforeMount中,可能会出现DOM还未渲染完成,这样会导致请求返回的数据无法正确渲染到页面上。

如果将ajax请求放在updated中,可能会造成无限循环的问题。因为ajax请求会导致数据发生变化,从而触发updated函数调用,而updated函数又会重新ajax请求,这样就会陷入死循环。

10、如何将组件所有props传递给子组件

在Vue中,可以使用v-bind指令将组件的所有props传递给子组件。具体来说,可以使用以下方式:

<template>
  <child-component v-bind="$props"></child-component>
</template>

在上面的代码中,我们使用了v-bind指令将组件的所有props传递给了子组件child-component。这样,在子组件中就可以直接使用这些props了。

需要注意的是,如果你使用了inheritAttrs选项将父组件的属性绑定到子组件上,那么你需要在子组件中使用$attrs来访问这些属性。例如:

<template>
  <child-component v-bind="$attrs"></child-component>
</template>

在上面的代码中,我们使用了$attrs来访问父组件的属性,并将它们传递给了子组件child-component。

11、如何自己实现v-model

可以通过以下步骤:

  1. 在组件中定义一个value属性和一个input事件。

  2. 在组件的模板中,将value属性绑定到表单控件的value属性上,并监听input事件,当表单控件的值发生变化时,触发input事件并将新的值作为参数传递出去。

  3. 在父组件中使用自定义的v-model时,将组件的value属性绑定到父组件的数据上,并监听input事件,当组件的值发生变化时,触发input事件并将新的值作为参数传递给父组件。

下面是一个简单的例子:

<!-- 自定义组件 -->
<template>
  <input :value="value" @input="handleInput">
</template>

<script>
export default {
  props: {
    value: String
  },
  methods: {
    handleInput(event) {
      this.$emit('input', event.target.value);
    }
  }
}
</script>

<!-- 父组件 -->
<template>
  <div>
    <my-input v-model="message"></my-input>
    <p>{{ message }}</p>
  </div>
</template>

<script>
import MyInput from './MyInput.vue';

export default {
  components: { MyInput },
  data() {
    return {
      message: ''
    }
  }
}
</script>

在上面的例子中,自定义组件MyInput定义了一个value属性和一个input事件,并将value属性绑定到表单控件的value属性上,并监听input事件,当表单控件的值发生变化时,触发input事件并将新的值作为参数传递出去。在父组件中,使用自定义的v-model时,将组件的value属性绑定到父组件的数据message上,并监听input事件,当组件的值发生变化时,触发input事件并将新的值作为参数传递给父组件,从而实现了双向绑定。

12、多个组件有相同的逻辑,如何抽离

可以通过mixin来抽离多个组件中的相同的逻辑。如果组件和mixin都定义了相同的选项,则优先使用mixin的。如果存在多个mixin被调用,则后面的mixin对象会覆盖前面的mixin对象中的选项。

13、何时要使用异步组件

通常情况下,需要加载大量组件时,使用异步组件可以减少应用的初始化加载时间。或者需要更好地管理代码分割时,可以使用异步组件来提高应用程序的性能和可维护性。

14、何时需要使用keep-alive

  1. 组件需要频繁的显示和隐藏
  2. 组件的状态需要缓存
  3. 组件需要异步加载

15、何时需要使用beforeDestory

  • 解绑自定义事件
  • 清除定时器
  • 解绑自定义的DOM事件

16、什么是作用域插槽

作用域插槽是Vue中的一个高级特性,它允许父组件向子组件传递一个带有作用域的插槽,让子组件可以在插槽内部访问父组件的数据和方法。

通常情况下,插槽只能传递简单的数据类型,比如字符串、数字等等。但是,当你需要在插槽内部访问复杂的数据结构,或者需要在插槽内部使用父组件的方法时,就可以使用作用域插槽来实现。

作用域插槽的使用方式与普通插槽类似,只需要在父组件中使用<slot>标签,并在该标签上添加一个名字,例如:

<template>
  <child-component>
    <template v-slot:default="slotProps">
      {{ slotProps.parentData }}
    </template>
  </child-component>
</template>

在子组件中,你可以通过$slotProps来访问父组件传递过来的数据和方法,例如:

<template>
  <div>
    <slot :parentData="data"></slot>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: 'Hello World'
    }
  }
}
</script>

17、Vuex中action和mutation有何区别

  • mutation只能执行同步操作,action可以用于异步操作
  • mutation可以被devtools跟踪,而action则不行。

18、Vue-router 常用的路由模式

有两种:hash模式和history模式。

  1. hash模式是指URL中的hash(#)符号来模拟一个完整的URL。
  2. history模式是指使用HTML5中的historyAPI来实现URL的变化。

如果不需要考虑SEO,可以选择hash模式,因为它兼容性好,不需要服务器端支持。如果需要考虑SEO,则选择history模式,因为它的URL更美观。

19、如何配置Vue-router异步加载

1、可以通过Webpack的动态import语法来实现。需要配置路由的path路径和component。 2、在webpack的配置文件中开启代码分割,以便将路由组件打包成独立的文件。

20、请用vnode描述一个DOM结构

{
  tag: 'div',
  props: {
    class: 'container',
    id: 'main'
  },
  children: [
    {
      tag: 'h1',
      props: {},
      children: 'Hello World!'
    }
  ]
}

这是一个包含一个div元素,它有一个class属性和一个id属性,它的子元素包括一个h1元素。

21、监听data变化的核心API是什么

Vue中监听data变化的核心API是Object.defineProperty。Vue通过这个API实现了数据劫持,可以在data属性变化时,能够自动触发更新操作。缺点是只能监听对象的属性,不能监听对象的新增属性和删除属性。还有如果对象的属性是嵌套对象,那么需要使用递归的方式来监听其内部属性的变化,

22、Vue如何监听数组变化

Vue会重新定义原型,重写push、pop等方法,实现监听。还可以使用watch来监听数组变化。

23、请描述响应式原理

Vue的响应式原理是通过数据劫持实现的。当Vue实例化时,它会遍历数据对象的每个属性,使用Object.defineProperty方法将它们转换为getter和setter。这样在数据发生变化时,setter会被调用,通知依赖于该数据的所有组件进行重新渲染。

vue组件渲染过程包括:

(1)解析模版:Vue会将组件的模版解析成一个抽象语法树(AST),这个AST描述了模版的结构和指令等信息。

(2)创建虚拟DOM:根据AST,Vue会创建一个虚拟DOM,它是一个轻量级的Javascript对象,描述了组件的结构和属性等信息。

(3)生成真实DOM:Vue会将虚拟DOM转换成真实DOM,并插入页面中。

(4)挂载组件:组件被挂载到页面后,Vue会调用组件的生命周期函数,执行一些初始化操作。

Vue组件更新过程包括:

(1)数据更新:当组件的数据发生变化时,Vue会自动触发数据更新。

(2)重新渲染虚拟DOM:Vue会根据数据变化,重新生成虚拟DOM。

(3)更新真实DOM:Vue会将新生成的虚拟DOM与旧的虚拟DOM进行比较,找出需要更新的部分,并将其更新到真实DOM中。

(4)调用生命周期函数:更新完成后,Vue会调用组件的生命周期函数,执行一些更新后的操作。

24、diff算法的事件复杂度

Vue中diff算法时间复杂度是O(n),其中n表示虚拟DOM树的节点数。然而在Vue2版本中,diff算法的时间复杂度是O(n^3),主要是因为在对虚拟DOM比较时,采用了一些暴力匹配的策略。为了优化这个问题,使用了几个策略:

  • 增加key属性:每个节点增加key属性,在比较虚拟DOM时,只对同一个key的节点进行比较。
  • 双端比较:从新旧节点的两端开始比较,依次向中间靠拢。
  • 拆分长列表:将其拆分成多个小列表,并分别进行比较。
  • patch补丁:在比较过程中,Vue会记录下所有需要进行变更的节点,一次性进行patch操作。

25、简述diff算法过程

  • 比较新旧虚拟DOM树的根节点,如果节点类型不同,则直接用新节点。
  • 如果节点类型相同,则比较节点属性,将新节点中有变化的属性更新到旧节点上。
  • 如果节点有子节点,则递归比较子节点,如果子节点有变化,则更新子节点。
  • 如果新节点的子节点数量大于旧节点,则将多余的子节点添加到旧节点上。
  • 如果新节点的子节点数量小于旧节点,则将多余的旧节点删除。

26、Vue为何是异步渲染,$nextTick何用

这是因为在Vue中,数据的更新会导致重新渲染,而重新渲染需要一定的时间。如果同步更新数据符合渲染组件,会导致用户界面卡顿,影响用户体验。因此,Vue采用异步渲染的方式,将数据更新和组件渲染分开,先更新数据,再在下一个时间循环中渲染组件,这样可以提高应用的性能和用户体验。

nextTick是Vue提供的一个方法,用于在组件渲染完成后执行回调函数。

27、Vue常见性能优化方式

  • 合理使用v-show和v-if
  • 合理使用computed
  • 使用v-for时配置key属性,以及避免和v-if同时使用
  • data层级不要太深
  • 使用vue-loader在开发环境做模版编译
  • 合理使用keep-alive
  • 自定义事件、DOM事件、定时器及时销毁
  • 合理使用异步组件
  • webpack层面的优化
  • 前端通用的性能优化,如图片懒加载
  • 使用SSR。服务器端渲染(Server Side Rendering)