Vue3 组件开发:生命周期钩子,组件之间通信全方案

一、生命周期钩子(组合式 API)

1.1 钩子总览

组合式钩子 对应选项式 触发时机 典型业务
onBeforeMount beforeMount 挂载前 极少用
onMounted mounted 挂载完成,DOM 可访问 操作 DOM、初始化图表
onBeforeUpdate beforeUpdate 数据变化、DOM 更新前 更新前处理
onUpdated updated DOM 更新后 依赖 DOM 的操作(慎用)
onBeforeUnmount beforeDestroy 卸载前 清理定时器、解绑事件
onUnmounted destroyed 卸载后 收尾

关键变化 :组合式 API 没有 beforeCreate / created ------setup 本身就在创建阶段执行,作用等同二者。钩子必须在 setup 顶层同步调用。

vue 复制代码
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";

const list = ref([]);
let timer: number | undefined;

onMounted(async () => {
  list.value = await fetchList();        // 请求数据
  timer = setInterval(() => {}, 1000);   // 启动定时器
});

onBeforeUnmount(() => {
  clearInterval(timer);                  // 必须清理,防内存泄漏
});
</script>

记忆口诀:onMounted 动 DOM 拉数据、onBeforeUnmount 清资源 。keep-alive 缓存组件还有 onActivated / onDeactivated。


二、父传子:props

2.1 defineProps 声明与类型校验

vue 复制代码
<!-- 子组件 Child.vue -->
<script setup lang="ts">
// 类型声明(编译期校验 + IDE 提示)
interface User {
  name: string;
  age: number;
}

// 方式一:纯 TS 类型
const props = defineProps<{
  title: string;
  user: User;
  count?: number;              // 可选
}>();

// 方式二:运行时校验 + 默认值(withDefaults)
const props2 = withDefaults(
  defineProps<{ count?: number; list: string[] }>(),
  {
    count: 0,
    list: () => [],            // 对象/数组默认值用函数返回
  }
);
</script>

<template>
  <h3>{{ title }}</h3>
  <p>{{ user.name }}</p>
</template>
vue 复制代码
<!-- 父组件 -->
<child title="标题" :user="userInfo" :count="5" />

2.2 单向数据流

props 是只读的 ,子组件不能修改(修改会告警且不生效)。要派生值用 computed,要改父数据用 $emit / defineModel。


三、子传父:defineEmits 自定义事件

vue 复制代码
<!-- 子组件 -->
<script setup lang="ts">
const emit = defineEmits<{
  change: [value: number];                    // 事件名 + 参数类型
  submit: [payload: { name: string }];
}>();

function handleClick() {
  emit("change", 42);                          // 触发事件并传参
}
</script>

<template>
  <button @click="handleClick">上报</button>
</template>
vue 复制代码
<!-- 父组件 -->
<script setup lang="ts">
function handleChange(val: number) {
  console.log("子组件上报:", val);
}
</script>

<template>
  <child @change="handleChange" />
</template>

四、组件双向绑定 defineModel(Vue 3.4+)

4.1 基本用法

vue 复制代码
<!-- 子组件:可双向绑定的输入框 -->
<script setup lang="ts">
const model = defineModel<string>();       // 声明双向绑定值

function clear() {
  model.value = "";
}
</script>

<template>
  <input v-model="model" placeholder="输入内容" />
</template>
vue 复制代码
<!-- 父组件 -->
<script setup lang="ts">
import { ref } from "vue";
const keyword = ref("");
</script>

<template>
  <my-input v-model="keyword" />
</template>

4.2 多个 v-model 与默认值

ts 复制代码
const visible = defineModel<boolean>("visible", { default: false });  // v-model:visible
const title = defineModel<string>("title");                            // v-model:title

底层等价于 modelValue + update:modelValue(或具名 xxx + update:xxx),Vue 3.4 起用 defineModel 一行搞定。


五、跨层级 provide / inject

解决祖先 → 任意后代的通信,免去逐层传 props。

ts 复制代码
// 祖先组件
import { ref, provide } from "vue";

const theme = ref("light");
const updateTheme = (val: string) => (theme.value = val);

provide("theme", theme);          // 提供响应式数据
provide("updateTheme", updateTheme);   // 提供修改函数(避免后代直接改)
ts 复制代码
// 后代组件(任意层级)
import { inject } from "vue";

const theme = inject<Ref<string>>("theme", ref("light"));   // 第二个参数是默认值
const updateTheme = inject<(v: string) => void>("updateTheme", () => {});
要点 说明
响应式 提供 ref(或 reactive + toRefs),不要提供普通值(会失去响应)
修改方式 同时 provide 修改函数,遵循单向数据流
键冲突 用 Symbol 或字符串常量统一管理

六、踩坑:props 只读、类型校验失效

坑 现象 解决
直接修改 props 告警 + 修改不生效 computed 派生 / defineModel / emit
props 类型校验"失效" 运行时无报错(TS 类型是编译期) 需要运行时校验用 withDefaults + 自定义 validator,或 defineProps 对象写法
defineModel 不生效 报"没有此宏" 升级 Vue 到 3.4+
provide 普通值 后代修改不同步 提供 ref 并传修改函数
inject 拿不到 父级未 provide 或键不一致 检查键名 + 提供默认值兜底
emit 事件名大小写 @myEvent 与 my-event 不匹配 统一用 kebab-case(my-event)

七、总结

  • 生命周期:6 个组合式钩子,setup 取代 beforeCreate/created,卸载前必清理;
  • 父传子 :defineProps + TS 类型 / withDefaults 默认值,只读单向流;
  • 子传父 :defineEmits 类型化声明 + $emit 传参;
  • 双向绑定 :defineModel(3.4+)一行实现,支持多个与默认值;
  • 跨层 :provide + inject(传 ref + 修改函数,保持单向流);
  • 踩坑:props 只读、运行时校验、3.4 版本要求、事件命名 kebab-case。
相关推荐
星栈19 分钟前
pnpm 12 升级实测
前端·javascript
Sirens.35 分钟前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
特创数字科技2 小时前
一个纯本地运行的图片处理工具:压缩 / 裁剪 / 九宫格 / 圆角 / 滤镜 / 拼图 / 水印,终生使用
前端
IT_陈寒3 小时前
Vue的v-if和v-for混用居然是个天坑
前端·人工智能·后端
天衍四九-3 小时前
【无标题】
前端·spring boot·mysql·nginx·docker
广州华水科技3 小时前
2026年单北斗GNSS变形监测系统推荐榜单,解锁GNSS位移监测新高度
前端
xcyxiner3 小时前
DicomViewer24 修复编译bug(window test 失败)
前端·qt
linux_cfan3 小时前
videojs v10 源代码系列解读:34 · `createComposition`:类型安全的冲突检测
前端·安全
utmhikari4 小时前
【AI原生】借助AI之力优化个人博客前端样式
前端·css·hexo·next·个人博客·ai-native·vibe coding