Skip to content

组件通信与内置组件

组件通信有哪些方式?

常见方式:

  • 父传子:props
  • 子传父:emit
  • 双向绑定:v-model
  • 跨层级:provide / inject
  • 全局状态:Pinia
  • 组件实例暴露:defineExpose
  • 插槽通信:slot props

面试回答时不要只背 API,可以补充适用场景:简单父子通信用 props/emit,跨页面共享状态用 Pinia,组件库内部跨层级依赖可用 provide/inject

defineProps 和 defineEmits 是什么?

<script setup> 中,defineProps 用来声明组件接收的属性,defineEmits 用来声明组件触发的事件。

vue
<script setup lang="ts">
const props = defineProps<{
  title: string
  count?: number
}>()

const emit = defineEmits<{
  change: [value: number]
}>()

function handleClick() {
  emit('change', 1)
}
</script>

它们是编译器宏,不需要从 vue 中导入。

v-model 在组件上是怎么实现的?

Vue3 中组件默认使用 modelValueupdate:modelValue 实现 v-model

父组件:

vue
<UserInput v-model="name" />

子组件:

vue
<script setup lang="ts">
defineProps<{
  modelValue: string
}>()

const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()
</script>

<template>
  <input
    :value="modelValue"
    @input="emit('update:modelValue', ($event.target as HTMLInputElement).value)"
  />
</template>

Vue3 还支持多个 v-model

vue
<UserForm v-model:name="name" v-model:age="age" />

keep-alive 有什么作用?

keep-alive 用来缓存组件实例,避免组件频繁销毁和重建。

常见场景:

  • Tab 页面切换
  • 列表页进入详情页后返回,保留筛选条件和滚动位置
  • 多步骤表单保留中间状态

被缓存组件会触发 onActivatedonDeactivated 生命周期。

Teleport 解决什么问题?

Teleport 可以把组件的一部分 DOM 渲染到当前组件层级之外的指定位置。

常见场景:

  • Modal
  • Drawer
  • Tooltip
  • Toast

例如弹窗组件逻辑属于当前页面,但 DOM 更适合挂到 body 下,避免被父级 overflowz-indextransform 影响。

vue
<Teleport to="body">
  <div class="modal">弹窗内容</div>
</Teleport>

Built with VitePress and GitHub Pages.