Vue3 初识组件
进入 Vue3 后,最核心的概念就是组件。简单说,页面上的一个区域(导航栏、卡片、整个页面)都可以拆成一个组件,组件可以嵌套、复用。
Vue3 推荐用 SFC(单文件组件,Single File Component) 的写法,一个 .vue 文件就是一个组件,把模板、逻辑和样式集中在一起,方便阅读和复用。
下面我们打开项目自带的 src/App.vue 来看。
组件结构
项目里的 App.vue 大致是这种结构:
<template>
<!-- ① 模板部分:编写页面结构(HTML 语法) -->
</template>
<script setup>
// ② 脚本部分:编写组件逻辑(JavaScript 语法)
</script>
<style>
/* ③ 样式部分:编写组件样式(CSS 语法) */
</style>
| 区块 | 作用 | 使用的语言 |
|---|---|---|
<template> |
定义页面结构 | HTML 语法 |
<script> |
定义数据、方法和生命周期逻辑 | JS / TS |
<style> |
定义组件样式,默认是全局,可加 scoped |
CSS |
局部样式
<style> 默认是全局的;加上 scoped(写作 <style scoped>)后,样式只对当前组件生效,避免污染其他组件。
组件逻辑
Vue 的组件逻辑有两种写法:
- 选项式 API(Options API):把数据、方法等放在不同的「选项」里分类组织的写法(会用到
data、methods等关键词,偶尔在旧资料里见到)。 - 组合式 API(Composition API):官方主推的写法,把逻辑按功能直接写在一起,更灵活,也是新项目的首选。
本教程采用 组合式 API,并统一使用它的语法糖 <script setup>,这种写法最简洁,也是新项目的首选。
你可能在老项目或网上资料里看到过 <script> 里写 setup(){} 并手动 return 的写法,两者背后是同一套概念,区别会在后面「常见疑问」里对比。
理论介绍完了,直接看例子。回到 App.vue,把 <template> 里换成变量,并在<script setup> 里声明它:
<script setup>
// 这里直接写 JavaScript,所有顶层变量自动暴露给模板使用
const msg = '你好,Vue3!'
</script>
<template>
<p>{{ msg }}</p>
</template>
这就是一个能正常跑起来的”入门版组件”,两个地方要注意:
<script setup>中的顶层变量、函数,模板可直接使用。- 模板里的
{{ }}是插值表达式,会把变量值显示出来。
响应式
上面的 msg 是写死的文字,就算在脚本里改它的值,页面也不会跟着变,这就像静态页面。
Vue 的响应式是指「数据一变,用到它的地方自动跟着更新」。
但普通的 JS 变量变了,Vue 感知不到,所以要用 ref 把数据包一层,让 Vue 能追踪它的变化:
<script setup>
import { ref } from 'vue'
const count = ref(0) // 响应式数据 count,初始值 0
</script>
<template>
<p>点击数:{{ count }}</p>
</template>
ref 返回的是一个对象,真正的值藏在 count.value 里。
所以操作 count 时只要记住两条规则:
- 脚本中:读写都要写
.value,例如count.value++。 - 模板中:Vue 会自动解包,直接写
count即可,不需要(也不能)写.value。
由此可以推出关键结论:脚本里改 count.value,模板中的 {{ count }} 就会自动刷新,显示的活交给模板,更新的活交给 Vue,脚本只管专心改数据。
到这里响应式就讲完了:脚本只负责改数据,显示和更新都交给 Vue。
至于「点击按钮怎么让数据变」,那属于事件处理,本篇先不展开,后面会有事件处理专门一篇讲解,这里先照着用即可。
组件示例
把上面学的整合起来,ref 存数据、{{ }} 显示、<style scoped> 管样式,就是一个完整的计数器组件 Counter.vue:
<template>
<div class="counter">
<!-- @click 是事件绑定(点击执行 add / reset),属于事件处理,后面会专门讲 -->
<p>当前值:{{ count }}</p>
<button @click="add">+1</button>
<button @click="reset">重置</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
const add = () => {
count.value++
}
const reset = () => {
count.value = 0
}
</script>
<style scoped>
.counter {
border: 1px solid #ddd;
padding: 16px;
border-radius: 8px;
text-align: center;
}
button {
margin: 0 8px;
padding: 4px 12px;
cursor: pointer;
}
</style>
把这个组件在 App.vue 里导入使用,刷新页面(开发服务器会自动热更新)就能看到效果:
<script setup>
import Counter from './components/Counter.vue'
</script>
<template>
<Counter />
</template>
Counter 写好了,怎么把它用到页面里、组件之间怎么互相引用?规则很简单,看下一节。
组件引用
上面的计数器只是单个组件,一个页面往往由多个组件拼装而成。
其实上一节已经用过了引用的写法:在 <script setup> 里 import 进来,模板里直接用组件名当标签——导入即用,不需要额外注册。
而且组件可以复用,import 一次,模板里想放几个就放几个,比如在页面上同时放两个计数器:
<script setup>
import Counter from './components/Counter.vue'
</script>
<template>
<Counter />
<Counter />
</template>
至此,你已经知道一个组件的三部分代码分别怎么写、组件之间怎么引用。
常见疑问
<script setup> 和<script> 区别
| 对比 | <script>(选项式 / 手写 setup) |
<script setup>(组合式语法糖) |
|---|---|---|
| 暴露数据 | 必须 return |
自动暴露 |
| 注册组件 | 需在 components 选项里注册 |
导入即用 |
| 写法 | 相对繁琐 | 极简 |
| 适用场景 | 老项目维护 | 新项目首选 |
可以同时使用 <script setup> 和普通 <script> 吗?
可以,但极少需要,那是处理特殊需求(如设置组件 name)时用的。新手阶段统一用 <script setup> 即可,不用管它。
速查卡片
| 要点 | 写法 |
|---|---|
| 组件文件 | .vue 文件(SFC) |
| 结构 | <template> + <script setup> + <style scoped> |
| 引入子组件 | import X from './X.vue' |
| 定义响应式数据 | const x = ref(初始值) |
| 脚本中读写 | x.value |
| 模板中使用 | 直接写 x |
掌握了这些,你已经能写出「自包含、可复用」的 Vue 组件了。