面试备战录

39 阅读3分钟

1、v-model是谁的语法糖

答:v-modelprops + events(双向绑定)的封装,在Vue2和Vue3中略有不同:

  • Vue2中一般是用来绑定在输入框input上,等价于:value + @input,子组件中通过$emit('input', newValue)通知父组件进行更新。
  • Vue3中<Child v-model="value" />等价于<Child :modelValue="value" @update:modelValue="value = $event" />
    • modelValue是默认的 prop 名,
    • update:modelValue 是默认的事件名

注:Vue3中支持一个组件上绑定多个v-model

<Child v-model:content="content"  v-model:title="title" />
// 等价于
<Child
  :title="title"
  @update:title="title = $event"
  :content="content"
  @update:content="content = $event"
/>

// 子组件
defineProps(['title','content'])
const emit = defineEmits<{
  (e: 'update:title', value: string): void;
  (e: 'update:content', value: string): void;
}>();

2、keep-alive如何实现缓存组建

答:<keep-alive>是Vue内置的一个抽象组件,用于缓存组件的状态,避免组件频繁销毁与重建,从而提升性能。它常用于切换的组件场景,比如:标签页(Tab)、页面切换等。

<template>
  <keep-alive>
    <component :is="currentView" />
  </keep-alive>
</template>

<script setup>
import A from './A.vue';
import B from './B.vue';
import { ref } from 'vue';

const currentView = ref('A'); // 切换为 B 就缓存 A 组件
</script>
  • 搭配router-view使用(页面缓存);
<!-- Vue Router 默认不会缓存页面,必须用 <keep-alive> 包裹 router-view 才能缓存页面组件。 -->
<template>
  <keep-alive>
    <router-view v-slot="{ Component }">
      <component :is="Component" />
    </router-view>
  </keep-alive>
</template>
  • 搭配 include / exclude 控制缓存范围;
<!-- 只缓存A、B组件 (A、B是组件的name)-->
<keep-alive include="A,B"> 
  <component :is="currentView" />
</keep-alive>
  • 生命周期感知:
    • activated / deactivated,缓存组件不会触发 mounted 和 unmounted
// 初次渲染时,会执行 onMounted 生命周期,也会执行 onActivated,但是缓存后就不执行 onMounted了,会执行onActivated
<script setup>
onActivated(() => {
  console.log('组件被激活(缓存中恢复)');
});

onDeactivated(() => {
  console.log('组件被缓存(离开但不卸载)');
});
</script>

3、Vue 生命周期

  • Vue3 生命周期:setup() → onBeforeMount() → onMounted() → onBeforeUpdate() → onUpdated() → onBeforeUnmount() → onUnmounted()
  • Vue2 生命周期:生命周期:beforeCreate → created → beforeMount → mounted -> beforeUpdate → updated -> beforeDestroy → destroyed

父子组件嵌套时:

  • 同步导入子组件时生命周期:父组件的setup() -> 父组件(onBeforeMount) -> 子组件setup() -> 子组件(onBeforeMount) -> 子组件(onMounted) -> 父组件(onMounted)
  • 异步导入子组件时生命周期:父组件的setup() -> 父组件(onBeforeMount) -> 父组件(onMounted) -> 子组件setup() -> 子组件(onBeforeMount) -> 子组件(onMounted)

4、vue2和vue3 的区别

答:Vue2 和 Vue3 在语法、性能、架构设计、API 风格等方面都有显著的区别。

  • 响应式系统原理Vue2通过Object.defineProperty()实现,Vue3使用Proxy实现;
  • Vue3支持组合式API,使其更适合复用和TS支持,适合大型项目结构化拆分;
  • 生命周期的不同:
    • Vue2 生命周期beforeCreate -> created -> beforeMount -> mounted -> beforeUpdate -> updated -> beforeDestroy -> destroyed
    • Vue3 生命周期 setup -> onBeforeMount-> onMounted -> onBeforeUpdate -> onUpdated -> onBeforeUnmount -> onUnmounted
  • Vue3 独有的一些新特性:
    • Fragment:可以有多个根节点组件
    • Teleport(传送门):组件内容可渲染到 DOM 任意位置
      • to:可以是标签上的 id,或者 body,需要是已经存在的节点
      • 会渲染到 <div id="custom-modal-root"></div> 标签内
        <div id="custom-modal-root"></div>
        <teleport to="#custom-modal-root">
          <div>可以传送到任意节点渲染</div>
        </teleport>
      
    • v-model 的多绑定支持
    • Suspense:异步组件更优雅加载
      • 用来出来异步组件加载的状态(如 loading、error)的内置组件,非常适合包裹defineAsyncComponent 或使用setup()中的异步逻辑。
     <Suspense>
      <template #default>
        <UserCard />
      </template>
    
      <template #fallback>
        <div>加载用户数据中...</div>
      </template>
    </Suspense>
    
    • 更好的TypeScript支持
    • script setup 语法糖
    • defineProps / defineEmits 简化逻辑
    • reactive, ref, computed, watch 全部可组合式使用
    • 增加了watchEffect
  • 性能方面
    • Vue3 使用 静态提升、Patch flag优化虚拟DOM diff过程;
    • 更小打包体积
    • 快速首次渲染和更新
  • Vite 支持 Vue3 更友好,Vue3 可以使用 @vue/runtime-core 创建自定义渲染器