Vue3 组件
组件是 Vue3 最核心的概念:把页面拆成"导航栏、轮播图、商品卡片"这样一个个独立且可复用的小块,每块自带模板、样式与逻辑。学会了组件化,代码才能从"几百行挤在一个文件里"走向清晰、可维护、可协作。
什么是组件
可以把组件理解成一个自定义的 HTML 标签:浏览器内置 <div>、<button>,而自定义的 <NavBar>、<ProductCard> 就是组件。使用时与普通标签差别不大,只是内部封装了数据与交互。
组件按使用范围分为两种:全局组件注册一次处处可用;局部组件只在自己文件里 import 使用,结构清晰,是日常开发的主流方式。
单文件组件的写法
日常开发使用 .vue 单文件组件(SFC),一个文件包含模板、脚本、样式三个部分:
<template>
<h2>{{ title }}</h2>
</template>
<script setup>
const title = '今日推荐'
</script>
<style scoped>
h2 { color: #42b883; }
</style>
style 上加 scoped 后,样式只作用于本组件,不会污染页面上的其他组件。
局部注册与使用
把子组件 import 进来,就能在父组件模板中像标签一样使用它,而且可以在多处重复引用:
<template>
<ProductCard />
<ProductCard />
</template>
<script setup>
import ProductCard from './components/ProductCard.vue'
</script>
效果:页面渲染出两份 ProductCard 的内容,两个实例互不干扰,各自维护自己的状态。
父传子:props
父组件通过自定义属性向子组件传数据,子组件用 defineProps 声明接收并直接使用:
<!-- 父组件 ProductList.vue -->
<template>
<ProductCard name="机械键盘" price="299" />
</template>
<script setup>
import ProductCard from './components/ProductCard.vue'
</script>
<!-- 子组件 ProductCard.vue -->
<template>
<div>
<h3>{{ name }}</h3>
<p>价格:{{ price }} 元</p>
</div>
</template>
<script setup>
defineProps({
name: String,
price: [String, Number],
})
</script>
数据是单向流动的:父组件数据变化,子组件自动更新显示;但子组件不能直接修改 props,保证数据流向清晰可预测。
子传父:$emit 事件
子组件通过 $emit 抛出事件并携带参数,父组件用 @事件名 监听处理,实现自下而上的通信:
<!-- 子组件中 -->
<button @click="$emit('add', 1)">加入购物车</button>
<!-- 父组件中 -->
<ProductCard @add="onAdd" />
<script setup>
const onAdd = (num) => console.log('数量 +', num)
// 效果:点击按钮后控制台输出"数量 + 1"
</script>
小结
组件把界面拆成可复用的积木:.vue 文件封装模板与逻辑,import 后随处可用;数据向下用 props 传,事件向上用 $emit 发。复杂页面无非是组件的层层组合,掌握这一节,后面的计算属性、监听与路由都是围绕组件展开的。