1、Vue组件基础:组件化思想、组件注册、组件命名规范、组件的基本结构
1.1 组件化思想:从“面条代码”到“乐高积木”
先聊聊组件化思想。说白了,就是把一个复杂的页面,拆成一个个独立的小模块。
我刚开始写前端那会儿,经常一个页面几千行代码。改一个按钮样式,得翻半天。后来接触了组件化,感觉就像从“煮面条”变成了“搭乐高”。每个组件只管自己的事,互不干扰。
组件化的核心价值在哪?
- 复用性:写一次,到处用。比如一个弹窗组件,项目里几十个地方都能引用。
- 可维护性:每个组件代码量少,出问题定位快。改一个组件,不影响其他地方。
- 协作效率:团队里每人负责几个组件,并行开发,互不冲突。
我的经验:组件化不是越细越好。我在项目中见过有人把“一个数字”都做成组件,结果光组件通信就写了一堆代码。适可而止,按业务模块拆分最合理。
1.2 组件注册:全局注册 vs 局部注册
Vue里注册组件有两种方式。我建议你根据场景选,别一股脑全用全局注册。
1.2.1 全局注册
用 Vue.component() 注册。注册后,任何地方都能直接用。
// main.js
import Vue from 'vue'
import MyButton from './components/MyButton.vue'
Vue.component('MyButton', MyButton)
优点:方便,不用每个页面都 import。缺点:打包时所有全局组件都会打进去,哪怕你没用。
我曾经踩过的坑:项目初期图省事,把所有组件都全局注册了。结果首屏加载慢得不行。后来改成按需加载,速度提升明显。
1.2.2 局部注册
在组件内部通过 components 选项注册。只有当前组件能用。
// ParentComponent.vue
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
}
}
我个人的习惯是:通用组件(比如弹窗、表格)用全局注册;业务组件(比如“用户信息卡片”)用局部注册。这样既方便又不会太臃肿。
1.3 组件命名规范:别让名字成为“坑”
命名这事,看着小,但影响很大。我见过项目里组件名五花八门,查起来头疼。
Vue官方推荐两种风格:
| 风格 | 示例 | 使用场景 |
|---|---|---|
| PascalCase(大驼峰) | MyComponent |
组件定义、模板中使用 |
| kebab-case(短横线) | my-component |
HTML模板、DOM中 |
几个实用规则:
- 前缀命名:比如
BaseButton、AppHeader、TheModal。一看就知道是基础组件还是业务组件。 - 语义化:别用
Comp1、Comp2。用UserAvatar、OrderList这种一眼能看懂的。 - 单文件组件:文件名用 PascalCase,比如
UserCard.vue。
小技巧:在模板里,Vue 会自动把 PascalCase 转成 kebab-case。所以你写 <MyComponent /> 和 <my-component /> 都行。但我建议统一用 PascalCase,更清晰。
1.4 组件的基本结构:一个 .vue 文件长什么样
一个标准的 Vue 单文件组件(SFC),包含三部分。嗯,这里要注意顺序:
<template>
<div class="my-component">
<h1>{{ title }}</h1>
<button @click="handleClick">点击</button>
</div>
</template>
<script>
export default {
name: 'MyComponent',
data() {
return {
title: 'Hello Vue'
}
},
methods: {
handleClick() {
alert('你点击了按钮')
}
}
}
</script>
<style scoped>
.my-component {
padding: 20px;
border: 1px solid #ccc;
}
</style>
拆开来看:
- <template>:写 HTML 结构。注意只能有一个根元素,我习惯用
<div>包一下。 - <script>:写 JavaScript 逻辑。包括数据、方法、生命周期等。
- <style>:写 CSS。加上
scoped属性,样式只对当前组件生效,不会污染全局。
避坑指南:scoped 不是万能的。它通过添加 data 属性实现样式隔离,但如果你用了子组件的根元素,样式还是能穿透的。我遇到过几次样式冲突,后来养成了给每个组件加唯一类名的习惯。
1.5 组件通信:父子组件怎么“说话”
组件之间需要传递数据。最基础的就是父子通信。
1.5.1 父传子:props
父组件通过属性传值,子组件用 props 接收。
// 父组件
<ChildComponent :message="parentMsg" />
// 子组件
export default {
props: {
message: {
type: String,
required: true
}
}
}
我个人建议:props 一定要写类型校验。不然传错类型,排查起来很痛苦。
1.5.2 子传父:$emit
子组件通过 $emit 触发事件,父组件监听。
// 子组件
this.$emit('update', newValue)
// 父组件
<ChildComponent @update="handleUpdate" />
你想想看,这种模式其实很符合直觉:父组件给指令,子组件汇报结果。
1.6 组件生命周期:组件从生到死
每个组件都有生命周期钩子。我常用的几个:
| 钩子 | 触发时机 | 常用场景 |
|---|---|---|
created |
实例创建后 | 初始化数据、调用 API |
mounted |
DOM 挂载后 | 操作 DOM、集成第三方库 |
beforeDestroy |
组件销毁前 | 清理定时器、取消订阅 |
我曾经犯过的错:在 created 里操作 DOM,结果拿不到元素。后来才明白,created 时 DOM 还没渲染,得用 mounted。
1.7 小结
组件化开发,说白了就是“分而治之”。把大问题拆成小问题,每个小问题用一个组件解决。
这一章我们聊了:
- 组件化思想:为什么拆、怎么拆
- 组件注册:全局 vs 局部,按需选择
- 命名规范:PascalCase + 前缀,清晰明了
- 基本结构:template + script + style,三剑客
- 通信与生命周期:父子传值、钩子时机
下一章,我们会深入组件的进阶用法。比如插槽、动态组件、异步加载。到时候再聊。
我的建议:学组件化,别光看。打开编辑器,写一个最简单的组件,注册、传值、触发事件,走一遍流程。比看十遍文章都管用。