前言
面试题在网络上有如海洋之深,对于同一知识点,每个人的理解也各有千秋。我们在面试中常常会遇到一个瞬息间脑海里一片空白的情况,其实这并不是因为我们不懂,而是因为我们在回答的时候缺乏一个清晰的思路。那么问题来了,我们如何能逐步唤醒自己的记忆,娓娓道来呢?
其他前端面试题精选
# 《如何在面试中娓娓道来》前端篇
方法展开
本篇从十个vue面试题案例逐步分解回答步骤,简单概括即为从一句简概的描述出发,将一个问题往自己擅长的部分引导。
比如vue面试题常常就会被问到3版本与2版本的比较。其实我们在准备过程中总会遇到这种多种特性描述一个问题的情况,引导式先将自己擅长的部分提出,后加展开描述,其实剩下的就是我们相对记忆薄弱的区块,就像答题我们先将会的答完,再挖掘自己需要“争取”的另一部分,这样既保证一部分得分,又不会因为没有章法而慌张。
Vue3
题目汇总
- 请解释Vue3中的Composition API是什么以及它的用途?
- Vue3中的reactive和ref有什么区别?
- 如何在Vue3中实现双向绑定?
- Vue3的Proxy是如何工作的?
- 请解释Vue3中的Teleport特性及其用途?
- 如何在Vue3中使用Suspense组件?
- Vue3中的script setup语法是什么?
- 如何在Vue3中使用provide和inject?
- vue3和vue2相比,有什么优化?
- 如何在Vue3中使用自定义指令?
解答篇
1. 请解释Vue3中的Composition API是什么以及它的用途?
引导式回答:
关键词:组合式API,区别于vue2的选项式API。
展开式回答:
Composition API是一种新的代码组织方式。
它是一个可选的、高级的、基于函数的API,可以让你更自由地组织和复用代码。与vue2的选项式api相比,Composition API允许你按照逻辑关系组织代码,你可以把相关的数据和方法组织在一起,形成一个可复用的逻辑单元,方便后期提取hooks。
这大大提高了代码的可读性和可维护性。(其实也算一种js写法的回归)
2. Vue3中的reactive和ref有什么区别?
引导式回答:
reactive
和ref
都是用来创建响应式数据的。
展开式回答:
最主要的区别在于:
reactive
是用来创建响应式对象的。你可以使用reactive
来包装一个普通的JavaScript对象,然后返回一个响应式的代理版本。这个代理会追踪其依赖,并在其依赖变更时进行更新。
const state = reactive({ count: 0 })
ref
是用来创建一个响应式的值的。它返回一个具有.value
属性的对象,这个对象的.value
属性是响应式的。你可以将ref
用于单个值,如字符串或数字。
const count = ref(0)
reactive
处理的是对象,你可以直接访问和修改对象的属性,无需使用.value
。ref
处理的是单个值,访问或修改值时,需要通过.value
属性。
3. 如何在Vue3中实现双向绑定?
引导式回答:
依赖于
v-model
指令。
展开式回答:
- 非自定义组件使用(普通使用):
<template><input v-model="message" />
</template><script>
import { ref } from 'vue';
export default {setup() {const message = ref('');return { message };},
};
</script>
- 自定义组件使用
在自定义组件上使用 v-model 时,情况会有些不同,组件内部必须通过 emits
选项显式地触发 'update:modelValue'
事件来更新父组件的数据。
- 首先,在自定义组件中,你需要接收一个名为
modelValue
的prop。这个prop代表了父组件希望与子组件双向绑定的值。
props: {modelValue: {type: String, // 或你需要的其他类型default: ''}
}
- 当需要更新这个值时,你需要在自定义组件中触发一个名为
update:modelValue
的事件,并传入新的值,如下:
this.$emit('update:modelValue', newValue);
然后你就可以在父组件中使用v-model
指令和你的自定义组件进行双向绑定了:
<YourComponent v-model="someValue" />
在这个例子中,当YourComponent
触发update:modelValue
事件时,父组件中的someValue
将会被更新为事件传入的新值。
4. Vue3的Proxy是如何工作的?
引导式回答:
Vue 会使用 Proxy 来包装原始数据,返回一个 Proxy 对象。
(首先提proxy对象——>后续描述修改对象的属性为思路)
展开式回答:
在 Vue3 中,Proxy 对象的作用可以被看作是一种"中间人"。
当你试图获取或修改 Proxy 对象的属性时,这些操作都会被 Proxy “拦截”。
当你尝试访问 Proxy 对象的某个属性时,Proxy 不仅会返回该属性的值,还会告诉 Vue 的响应式系统:“嘿,有人正在访问这个属性。”于是,Vue 就会记下这个操作,将当前的“副作用”(比如渲染函数或计算属性)添加到这个属性的依赖列表中。这样,Vue 就能知道哪些副作用依赖于这个属性。
当你尝试修改 Proxy 对象的某个属性时,Proxy 不仅会改变该属性的值,还会告诉 Vue 的响应式系统:“嘿,有人刚刚修改了这个属性。”于是,Vue 就会找到所有依赖于这个属性的副作用,并重新运行它们,以确保它们使用的是最新的属性值。
通过这种方式,Proxy 对象帮助 Vue 有效地追踪和管理响应式数据的变化,从而实现数据和视图的同步更新。
5. 请解释Vue3中的Teleport特性及其用途。
引导式回答:
关键词:传送门。
将子组件模板部分渲染到DOM的其他位置(顾名思义:传送效果)。
展开式回答:
这个特性在很多场景下都非常有用。
例如,你可能要创建一个模态框(modal),这个模态框要覆盖整个页面,而不仅仅是它的父组件。在 Vue 2 中,你可能需要通过全局组件或其他方法来实现这个功能,但这往往会导致代码的复杂性增加。
而在 Vue 3 中,你可以使用 Teleport 来轻松实现这个功能。
你可以通过 <teleport to="目标元素的选择器">
来使用 Teleport。
例如:
<teleport to="#modal-container"><div class="modal"><!-- 模态框的内容 --></div>
</teleport>
在这个例子中,<div class="modal">
会被渲染到 id 为 modal-container
的元素内,而不是它的父组件内。
6. 如何在Vue3中使用Suspense组件?
引导式回答:
<Suspense>
是一个内置组件,就好像一个包住礼物的盒子。(盒子的表面是#fallback的内容,其中的礼物是#default正在准备的东西)
展开式回答:
使用 <Suspense>
的基本步骤如下:
- 在你的组件模板中,使用
<Suspense>
包裹起你的异步组件。
<Suspense><template #default><AsyncComponent /></template><template #fallback><div>Loading...</div></template>
</Suspense>
- 在上面的代码中,
<AsyncComponent />
是你的异步组件,它可能是通过defineAsyncComponent()
或者import()
动态加载的组件。 #default
插槽用于放置异步组件,#fallback
插槽则用于放置备用内容,这个备用内容会在异步组件加载过程中显示。
7. Vue3中的script setup语法是什么?
引导式回答:
关键词:解析语法糖。用于大幅简化组件的写法。
展开式回答:
<script setup>
import { ref } from 'vue';let count = ref(0);
function increment() {count.value++;
}
</script>
在模板中,我们可以直接使用在 <script setup>
中定义的响应式数据和方法,就像它们被定义在 data
或 methods
中一样。
此外,<script setup>
还可以和 defineProps
和 defineEmits
函数一起使用,用于定义组件的 props
和自定义事件。经过这样的改写,整个组件的结构会变得更加清晰。
8. 如何在Vue3中使用provide和inject?
引导式回答:
provide
和inject
是一对用于依赖注入的 API,主要用于实现组件之间的通信。
展开式回答:
假设我们有一个父组件,我们可以在其中提供一个名为 theme
的数据:
<template><div><ChildComponent /></div>
</template><script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';let theme = ref('light');
provide('theme', theme);
</script>
然后,在任何子组件或孙子组件中,我们都可以使用 inject
来接收这个 theme
数据:
<template><div :class="theme">I'm a child component</div>
</template><script setup>
import { inject } from 'vue';let theme = inject('theme');
</script>
注意几个关键点:
- provide 和 inject 主要解决了 Vue 中跨级组件间通信的问题。
- provide 和 inject 都可以接收两个参数。第一个参数是提供或注入的属性的名称,第二个参数可选,表示当无法找到提供的属性时要使用的默认值。
- 使用 provide 和 inject 的组件并不需要保持直接的父子关系,只要是在一个组件树内,就可以通过这种方式进行数据传递。
- 子组件可以覆盖沿组件树向上注入的值,这可能会对你实例树的其他部分产生影响,因此你需要时刻注意这一点。
- 在 Vue 2.x 中,provide 和 inject 是选项;而在 Vue 3 中,它们成为了两个函数。
9. vue3和vue2相比,有什么优化?
引导式回答:
更快(速度、体积…) 更简单(setup…) 更强(新特性:传送门、Suspense…)
展开式回答:
- 性能提升:Vue 3 在性能方面做了大量优化。它的渲染速度比 Vue 2 快约 1.5~2 倍,而且打包尺寸减少了约 41%。
- Composition API:这是 Vue 3 的一个主要特性,它提供了一种更灵活的方式来组织和管理组件的逻辑。这使得在大型项目中管理复杂状态变得更加容易。
- 更好的 TypeScript 支持:Vue 3 从一开始就用 TypeScript 重写,因此它提供了更好的 TypeScript 支持。
- Fragments:在 Vue 2 中,每个组件必须有一个根元素。但在 Vue 3 中,这个限制被取消了。你可以在一个组件中返回多个根节点,这几乎消除了所有需要额外 DOM 元素的需求。
- 更好的自定义指令 API:在 Vue 3 中,自定义指令的 API 更加一致和强大。
- Suspense 组件:Vue 3 介绍了 Suspense 组件,用于在组件等待异步操作完成时提供回退内容。
- 实验性的
<script setup>
语法:Vue 3.2 引入了<script setup>
语法,它提供了一种更紧凑的方式来编写单文件组件。 - 其他新特性包括:对于 Portal 的原生支持,更强大的计算属性,多个 v-model 支持,以及更好的安全性。
10. 如何在Vue3中使用自定义指令?
引导式回答:
关键词:directive
展开式回答:
我们来创建一个自定义指令叫 v-focus,当页面加载完毕后,此指令可以使一个输入框自动获取焦点。
先定义自定义指令:
import { createApp } from "vue";const app = createApp({});app.directive("focus", {// 当被绑定的元素挂载到 DOM 上时mounted(el) {// 获取焦点el.focus();}
});
然后在模板中使用自定义指令:
<template><input v-focus />
</template>
自定义指令对象可以接受一些函数作为参数:
beforeMount
:与 Vue 2 中的bind
钩子相对应,一旦指令被绑定到元素上,就会立即调用这个函数,而不必等到节点插入到 DOM 中。mounted
:与 Vue 2 中的inserted
钩子相对应,一旦绑定的元素插入到父节点中,这个函数就会被调用。beforeUpdate
:在元素更新之前触发。updated
:在元素更新之后触发。beforeUnmount
:在指令从元素上卸载前触发。unmounted
:在指令从元素上卸载后触发。
这些函数可以接受三个参数:el
,binding
和 vnode
,分别代表指令绑定的元素,绑定对象以及虚拟节点。