一. 组件定义与父子组件传值
把页面拆成小块代码,一块独立功能就是组件,可以重复使用。
分两类:
父组件:引入、使用别人的组件
子组件:被引入、接收父传数据
父组件
<script setup lang="ts"> import Child from './Child.vue' // 引入子组件 </script> <template> 我是父组件 <br> <Child/> </template>子组件用 defineProps 接收
<script setup lang="ts"> // 父组件 -> 子组件传值 // props作用:父组件给子组件传递数据 const props = defineProps({ msg: { type: String, // 限定字符串 required: false, // 非必传 default: "未传值" // 不传时默认值 } }) </script> <template> <div> 我是子组件 <br> 传值:{{ msg }} <br> </div> </template>二. 子传父:defineEmits(配套补充)
父组件
<script setup lang="ts"> import Child from './Child.vue' // 引入子组件 import {ref} from 'vue' // 引入子组件 const msg = ref('父组件原值') const getMsg = (value: string) => { msg.value = value } </script> <template> 我是父组件 <br> 子组件传的值:{{ msg }} <Child @change-msg="getMsg"/> </template>子组件
<script setup lang="ts"> // 子组件 - > 父组件传值 const emit = defineEmits<{ 'change-msg': [msg: string] }>() const send = () => { emit('change-msg', '子组件传给父组件') } </script> <template> <div> 我是子组件 <br> <button @click="send">传值给父组件</button> </div> </template>三. 生命周期
生命周期:组件从创建 → 渲染页面 → 更新 → 销毁全过程自动触发的函数。
Vue3 在 setup 里使用,必须先导入,不能写在函数 / 异步里面。
一. 执行完整顺序(从上到下)
setup()和<script setup>最先执行(比所有生命周期都早)- onBeforeMount:DOM 还没渲染,页面空白
- onMounted:DOM 渲染完成,页面元素已经存在(最常用)
- onBeforeUpdate:数据变了,页面还没更新
- onUpdated:页面 DOM 更新完毕
- onBeforeUnmount:组件销毁前,DOM 还在
- onUnmounted:组件销毁完成,DOM 被移除
二. 父子组件执行顺序
- 父 setup
- 父 onBeforeMount
- 子 setup
- 子 onBeforeMount
- 子 onMounted
- 父 onMounted
三. 高频使用场景记忆
- 一进页面请求接口、获取 DOM → onMounted
- 组件关闭清除定时器 / 监听 → onUnmounted
- 数据变化后操作最新 DOM → onUpdated
四. 组件拆分复用
拆分组件可以使得代码解耦、可复用、提高可维护性。拆分原则要遵循单一职责、可复用、层级拆分等。
基础复用 - 全局公共组件
定义全局组件、在main.ts全局注册,后续使用不需要导入
import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import Card from './components/Card.vue' // 全局组件 const app = createApp(App) app.use(createPinia()) app.component('Card', Card) // 全局注册 app.mount('#app')使用全局注册的公共组件
<script setup lang="ts"> // import Card from './Card.vue'; </script> <template> 我是父组件<br> <!-- 不需要导入,可以直接使用 --> <Card/> </template>