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 发。复杂页面无非是组件的层层组合,掌握这一节,后面的计算属性、监听与路由都是围绕组件展开的。

笔记加载中…