2024最新五道vue面试题,你来试试!

哈喽,大家好,今天这篇文章由我们我们的金牌导师Uncle13提供,作为多年大厂前端面试官,以及和学员们面试经历总结,来看看由哪些值得我们关注的前端面试题吧。

1,Vue中子组件是否能使用未定义的 props ?

在 Vue.js 中,子组件默认情况下不能使用未在 props 选项中明确声明的属性。Vue 的组件系统设计旨在明确组件之间的接口,其中 props 作为组件公开的属性,必须被明确声明。这一设计原则增强了代码的可读性和可维护性,确保了组件之间通信的清晰和有序。

默认情况下的限制

Vue 强制要求子组件只能使用在 props 中明确声明的属性,这有助于避免潜在的命名冲突和意外的行为。然而,在某些情况下,我们可能需要在子组件中访问来自父组件的额外数据,这些数据并未在 props 中声明。

绕过限制的方法
  1. 使用 $attrs

尽管子组件不能直接使用未声明的 props,但它可以通过 $attrs 对象来接收来自父组件的非 props 属性。$attrs 包含了传递给组件但未被 props 接收的所有属性(包括 classstyle,以及绑定的事件监听器,如果 inheritAttrs 配置为 false 的话)。

子组件示例

<template>
<div>{{ $attrs.someProp }}</div>
</template>

<script>
export default {
// 如果你不希望组件的根元素自动继承这些属性,可以设置 inheritAttrs: false
inheritAttrs: false,
};
</script>
  1. 使用 $props(不推荐)

虽然技术上可以通过 this.$props 访问到所有通过 props 传递的属性,但如果你尝试访问一个未声明的 prop,Vue 会发出警告,并且不会阻止你访问该属性的值(尽管这可能不是预期的行为)。然而,这种做法不推荐,因为它破坏了组件接口的清晰性,可能导致难以理解和维护的代码。

注意:实际上,$props 并不是 Vue 实例直接提供的属性,这里可能是对 this$options.propsData 的误解。直接使用未声明的属性通常不会通过 $props 访问,而是直接尝试访问组件实例上的属性,这会导致运行时警告。

最佳实践

始终在子组件中明确声明你打算使用的所有 props

这样做有以下几个好处:

  • 接口清晰:明确的 props 声明使得组件的接口一目了然,便于其他开发者理解和使用。
  • 减少错误:强制声明 props 有助于减少因属性名拼写错误或误用而导致的运行时错误。
  • 易于维护:当组件的接口发生变化时,明确的 props 声明使得更新和维护变得更加容易。

对于需要处理来自父组件的额外数据但又不想在 props 中声明的场景,使用 $attrs 是推荐的方式。这不仅可以保持组件接口的整洁和明确,还可以提供额外的灵活性,特别是在构建高度复用的组件库时。

2, vue 全局注册组件很方便,为何不都是用全局注册?

Vue 中全局注册组件提供了一种便捷的方式来在应用的任何位置使用这些组件,但它并非总是最佳选择,原因主要有以下几点:

  1. 命名冲突:全局注册的组件在所有组件中都是可用的,这可能导致命名冲突。如果你的项目中包含了多个库或插件,它们可能会注册一些同名的组件,这将导致不可预测的行为。

  2. 性能考虑:虽然现代浏览器的性能已经足够强大,但全局注册组件可能会略微影响应用的性能,尤其是在大型应用中。因为每次组件渲染时,Vue 都需要检查全局注册的组件是否应该被渲染。如果应用中有大量全局注册的组件,但实际上只在少数几个地方使用,那么这种检查就显得多余了。

  3. 封装性:全局注册组件破坏了组件的封装性。理想情况下,组件应该只关心其内部逻辑和界面,而不应该关心它们是如何被注册或使用的。全局注册使得组件的使用变得无处不在,这可能会降低代码的可维护性和可读性。

  4. 模块化:随着 Vue 应用的增长,模块化变得尤为重要。全局注册组件与模块化开发的原则相悖。在模块化开发中,我们希望每个模块或组件都是独立的,并且可以很容易地在不同的项目或应用之间重用。全局注册组件使得这种重用变得困难,因为你需要确保新项目中没有与全局组件同名的组件。

  5. 懒加载:全局注册的组件无法利用 Vue 的异步组件和代码分割功能来实现懒加载。这意味着无论用户是否需要这些组件,它们都会在应用的初始加载时被加载到浏览器中,这可能会增加应用的初始加载时间。

  6. 可维护性:随着项目的增长,全局注册的组件可能会变得难以管理和维护。你可能需要花费更多的时间来查找和更新这些组件,因为它们可能散布在应用的各个角落。

因此,尽管全局注册组件在某些情况下可能很方便,但在大多数大型或复杂的 Vue 应用中,建议采用局部注册或按需注册的方式来管理组件。这样可以提高应用的性能、可维护性和模块化程度。

3,vue3 里面 <script setup> 作用是什么?

在 Vue 3 中,<script setup> 是单文件组件(Single-File Components, 简称 SFC)中的一个编译时增强特性,它为组件提供了一种更简洁、更高效的编写方式。这个特性是 Vue 3 Composition API 的一部分,旨在通过更少的样板代码和更直观的语法来增强开发者的体验。

<script setup> 的主要作用和特点包括:

  1. 更简洁的语法:在 <script setup> 中,你不需要显式地定义 export default,组件的选项(如 props、emits、components 等)会自动从 <script setup> 的上下文中“暴露”出来。这大大减少了模板和脚本之间的样板代码。

  2. 更好的 Composition API 支持<script setup> 与 Vue 3 的 Composition API 配合得天衣无缝。它允许你使用 Composition API 定义的响应式状态、计算属性、方法等,而无需将它们包裹在 setup() 函数中。这使得代码更加直观和易于管理。

  3. 更好的 TypeScript 支持<script setup> 提供了对 TypeScript 的原生支持,能够自动推断出 props、emits 等的类型,从而减少了类型注解的需要。

  4. 使用 <script setup> 的限制

    • 顶层的绑定(如 propsemitscontext 等)会自动暴露给模板,但不会在 <script setup> 的代码中直接可用。如果你需要在 <script setup> 中访问这些值,你可以使用 definePropsdefineEmits 这两个编译器宏(compiler macros)。
    • <script setup> 中的代码是编译时增强的,因此它不支持在 <script setup> 中直接访问普通的 <script> 标签中声明的变量或函数。
    • 由于 <script setup> 是编译时特性,因此它不支持在运行时动态地更改组件的选项或行为。


4,Vue侦听器在什么情况下是需要清理副作用的?

在 Vue 3 中,清理副作用主要指的是在一个响应式侦听器(如 watchwatchEffect)中,当侦听的响应式状态(或侦听的回调函数)重新执行之前或组件销毁时,移除或停止之前创建的资源,以避免内存泄漏、性能问题或意外的行为。以下是一些需要清理副作用的典型情况及其处理方式:

1. 使用定时器时

当你在侦听器的回调函数中设置了定时器(如使用 setIntervalsetTimeout),并且不希望这个定时器在回调函数下次执行时仍然活动,你就需要在回调函数下一次执行之前清理这个定时器。

watchEffect((onInvalidate) => {
  const timer = setInterval(() => {
    // 执行一些逻辑
  }, 1000);

  // 清理函数
  onInvalidate(() => {
    clearInterval(timer);
  });
});
2. 订阅外部或异步资源时

当你订阅了一些外部资源,如 WebSocket 连接、外部 API 的实时数据流、或是自定义事件监听器,如果这些资源在组件卸载后继续活动,可能会导致内存泄漏或其他意外行为。

watchEffect((onInvalidate) => {
  const ws = new WebSocket("ws://example.com/feed");

  ws.onmessage = (message) => {
    // 处理消息
  };

  // 侦听器清理函数
  onInvalidate(() => {
    ws.close();
  });
});
3. 响应式引用发生变化时

当你侦听的响应式引用(如 refreactive 对象)在回调函数生命周期中发生变化时,如果回调产生了外部副作用(比如修改了外部状态、操作了 DOM、设置了全局事件监听器等),你可能需要清理这些副作用,避免它们在重新计算或组件卸载时造成问题。

const user = ref(null);

watchEffect((onInvalidate) => {
  // 假设 fetchUser 返回一个取消订阅或清理资源的函数
  const unsubscribe = fetchUser(user.value, (newUser) => {
    user.value = newUser;
  });

  onInvalidate(() => {
    unsubscribe();
  });
});
为什么要清理副作用

清理副作用是为了防止不必要的资源占用和潜在的内存泄漏,尤其是在使用外部资源、设置定时器、或订阅数据时。Vue 提供的 onInvalidate 回调允许在侦听器重新运行之前或组件销毁时执行清理逻辑,确保应用资源被适当管理和释放。这不仅有助于维护应用的性能和稳定性,还能防止潜在的内存泄露问题,使得应用更加健壮和可靠。

5,选项式 API 和组合式 API,两者有何区别,该如何取舍?

Vue.js 的选项式 API(Options API)和组合式 API(Composition API)是两种不同的代码组织和复用模式,它们各自具有独特的特点和适用场景。下面我们来详细探讨它们的区别以及如何取舍,并通过示例来说明。

选项式 API(Options API)

在 Vue 2.x 中引入的默认 API,主要通过将组件的选项组织在单个对象中来工作。这个对象可以包含如 datacomputedmethodswatchmountedupdated 等属性。

优点

  • 结构清晰,易于上手。特别是对于 Vue 的新手来说,按照组件的选项来组织代码更直观。
  • 逻辑自然分组,按照 Vue 的生命周期或选项进行组织。

缺点

  • 随着组件复杂度的增加,可能很难追踪数据流向和逻辑来源。
  • 当需要在多个组件之间复用逻辑时,可能需要使用 mixin 或者高阶组件,这可能会导致状态管理和依赖关系的复杂性增加。
组合式 API(Composition API)

Vue 3.x 引入的一种新的 API,允许将组件的逻辑相关的代码组织在一起,利用 setup 函数作为组件的入口点,并在其中使用如 refreactivecomputedwatchwatchEffect 等 API 来声明响应式状态和逻辑。

优点

  • 更好的逻辑复用。可以更容易地将可复用的逻辑组织成自定义的 hook,然后在组件之间共享。
  • 更灵活的代码组织。允许按照逻辑来组织代码,而不是按照选项来组织。
  • 更好的 TypeScript 支持。由于可以更直接地处理响应式状态和函数,组合式 API 在使用 TypeScript 时能提供更精确的类型推断。

缺点

  • 相比选项式 API,可能需要更长的学习曲线。
  • 在某些情况下,可能需要更多的代码来达到相同的功能,特别是当使用大量响应式状态或计算属性时。

假设我们有一个计数器组件,我们可以分别用选项式 API 和组合式 API 来实现它。

选项式 API 示例

<template>
<div>
<p>{{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>

<script>
export default {
data() {
return {
count: 0
};
},
methods: {
increment() {
this.count++;
}
}
}
</script>

组合式 API 示例

<template>
<div>
<p>{{ count.value }}</p>
<button @click="increment">Increment</button>
</div>
</template>

<script>
import { ref } from 'vue';

export default {
setup() {
const count = ref(0);

function increment() {
count.value++;
}

return {
count,
increment
};
}
}
</script>
如何取舍?
  • 对于新项目或想要更好地利用 Vue 3 特性的项目,推荐使用组合式 API。
  • 如果你已经在使用 Vue 2,并且团队熟悉选项式 API,可以继续使用它,直到有迁移到 Vue 3 的需求。
  • 对于逻辑较为简单的组件,选项式 API 可能仍然是一个很好的选择。
  • 当需要编写可复用的逻辑或高度依赖 TypeScript 时,组合式 API 提供了更好的支持。

最后

还没有使用过我们刷题网站(https://fe.ecool.fun/)或者刷题小程序的同学,如果近期准备或者正在找工作,千万不要错过,题库主打题库全和更新快哦~。

有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。