
文章目录
- [Ⅰ. 组件及组件化](#Ⅰ. 组件及组件化)
-
- 一、为什么需要组件?
-
- [1. 思考](#1. 思考)
- [2. 解决方案](#2. 解决方案)
- 二、组件及组件化
-
- [1. 组件](#1. 组件)
- [2. 组件化](#2. 组件化)
- [三、根组件 `App.vue`](#三、根组件
App.vue) -
- [1. 根组件](#1. 根组件)
- [2. 组件是由三部分构成](#2. 组件是由三部分构成)
- 四、组件的使用
-
- [1. 创建组件](#1. 创建组件)
- [2. 导入组件](#2. 导入组件)
- [3. 注册组件💥](#3. 注册组件💥)
- [4. 使用组件](#4. 使用组件)
- [5. 练习](#5. 练习)
- 五、组件的全局注册
-
- [1. 步骤](#1. 步骤)
- [2. 使用组件(与局部组件一样)](#2. 使用组件(与局部组件一样))
- [3. 注意](#3. 注意)
- [4. 语法](#4. 语法)
- [5. 练习](#5. 练习)
Ⅰ. 组件及组件化
一、为什么需要组件?
1. 思考
以可折叠面板为例,现要展示3个,如何操作?
可折叠面板案例的代码:
javascript
<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>
<template>
<h3>可折叠面板</h3>
<div class="panel">
<div class="title">
<h4>自由与爱情</h4>
<span class="btn" @click="visible = !visible"> {{ visible ? '收起' : '展开' }} </span>
</div>
<div class="container" v-show="visible">
<p>生命诚可贵,</p>
<p>爱情价更高。</p>
<p>若为自由故,</p>
<p>两者皆可抛。</p>
</div>
</div>
</template>
<style lang="scss">
body {
background-color: #ccc;
}
#app {
width: 400px;
margin: 20px auto;
background-color: #fff;
border: 4px solid green;
border-radius: 1em;
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);
padding: 1em 2em 2em;
}
#app h3 {
text-align: center;
}
.panel {
.title {
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #ccc;
padding: 0 1em;
}
.title h4 {
line-height: 2;
margin: 0;
}
.container {
border: 1px solid #ccc;
padding: 0 1em;
border-top-color: transparent;
}
.btn {
cursor: pointer;
}
}
</style>
2. 解决方案
- 把需要复用的一段标签,抽离并封装到一个单独的
vue文件里,连同相关JS和CSS放到一起 - 哪里要用这个组件,哪里导入,当做标签使用即可
新建一个 src/components/MyPanel.vue 文件:
javascript
<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>
<template>
<div class="panel">
<div class="title">
<h4>自由与爱情</h4>
<span
class="btn"
@click="visible = !visible">
{{ visible ? '收起' : '展开' }}
</span>
</div>
<div
class="container"
v-show="visible">
<p>生命诚可贵,</p>
<p>爱情价更高。</p>
<p>若为自由故,</p>
<p>两者皆可抛。</p>
</div>
</div>
</template>
<style lang="scss" scoped>
.panel {
.title {
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #ccc;
padding: 0 1em;
}
.title h4 {
line-height: 2;
margin: 0;
}
.container {
border: 1px solid #ccc;
padding: 0 1em;
border-top-color: transparent;
}
.btn {
cursor: pointer;
}
}
</style>
然后在 App.vue 导入并使用该组件:
javascript
<script setup>
// 导入
import MyPanel from './components/MyPanel.vue'
</script>
<template>
<h3>可折叠面板</h3>
<!-- 使用 -->
<MyPanel />
<MyPanel />
<MyPanel />
</template>
<style>
body {
background-color: #ccc;
}
#app {
width: 400px;
margin: 20px auto;
background-color: #fff;
border: 4px solid green;
border-radius: 1em;
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);
padding: 1em 2em 2em;
}
#app h3 {
text-align: center;
}
</style>

二、组件及组件化
1. 组件
组件是一个 独立的、可复用 的 Vue 实例,也是一段 独立的 UI 视图 ,代码上体现在是一个独立的 .vue 文件,包含 JS + HTML + CSS 三部分组成。
类似乐高和积木一样,我们可以通过任意的乐高或积分进行组合,拼装成我们需要的成品。

2. 组件化
定义: 一种代码的开发思想,体现在一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为;通过 组件的组合与拼装 形成一个完整的页面,本质是代码的一种拆分思想,化大为小、化繁为简、分而治之。
好处: 各自独立、便于复用
比如:下面这个页面,可以把所有的代码都写在一个页面中,但是这样显得代码比较混乱,难以维护。我们可以按模块进行组件拆分

三、根组件 App.vue
1. 根组件
根组件是整个应用最上层的组件,包裹所有普通小组件,如下图所示:

2. 组件是由三部分构成
- template:HTML 结构
- script:JS 逻辑
- style:CSS 样式(可支持less/scss,需要装包)
- 让组件支持less/scss
- style标签,lang="less/scss"开启less/scss功能
- 装包:
npm i less less-loader -D或者npm i sass -D
四、组件的使用
组件的一系列场景命名规范如下所示:
| 场景 | ✅推荐写法 | 可选写法 | 说明 |
|---|---|---|---|
| 文件名 | MyHeader.vue | my-header.vue | 官方推荐 PascalCase,和类名一样清晰 |
| import 引入 | import MyHeader from './MyHeader.vue' | import Haha from './MyHeader.vue' | 变量名随意,但最好和文件名一致,便于阅读 |
| 局部注册 | components: { MyHeader } | components: { Haha } | 名字和模板里的标签要对应 |
| 模板 (SFC 内部) | Vue 自动识别两种形式 | ||
| HTML 文件直接写 (非 .vue) | ❌ 不支持 | HTML 标签不区分大小写,必须用短横线 |
1. 创建组件
新建 .vue 文件,编写组件的三部分代码
2. 导入组件
在需要的 vue 文件中的 <script setup> 中导入需要的组件即可!
注意:导入的组件对象名称,推荐保持和文件名一致。
javascript
import 组件对象 from '相对路径'
// 例子:
import MyPanel from './components/MyPanel.vue'
3. 注册组件💥
💥注意:局部组件无需注册 ,全局组件要在 main.js 中注册。
之所以局部组件不需要注册,是因为 vue3 中 <script setup> 自动完成了局部注册 ,如果是 vue2 或者普通的 <script> 的话,则需要手动注册局部组件,如下面所示:
javascript
<script>
import MyHeader from './components2/MyHeader.vue'
// 如果是 vue2 或者普通的 <script> 的话,则需要手动注册局部组件
export default {
components: {
MyHeader
}
}
</script>
<template>
<my-header></my-header>
</template>
4. 使用组件
把组件当做自定义标签使用:(单双标签均可)
javascript
<组件名></组件名>
<组件名 />
// 例子:
<!-- 大驼峰 双标签 -->
<MyPanel></MyPanel>
<!-- 大驼峰 自闭合的单标签 -->
<MyPanel />
<!-- 烤串法(更推荐这种) 双标签 -->
<my-panel></my-panel>
<!-- 烤串法 自闭合的单标签 -->
<my-panel />
5. 练习
components2/MyHeader.vue文件:
javascript
<script setup></script>
<template>
<div class="my-header">我是my-header</div>
</template>
<style>
.my-header {
height: 100px;
line-height: 100px;
background-color: #8064a2;
}
</style>
components2/MyMain.vue文件:
javascript
<script setup></script>
<template>
<div class="my-main">我是my-main</div>
</template>
<style>
.my-main {
height: 400px;
margin: 20px 0;
line-height: 400px;
background-color: #f79646;
}
</style>
components2/MyFooter.vue文件:
javascript
<script setup></script>
<template>
<div class="my-footer">我是my-footer</div>
</template>
<style>
.my-footer {
height: 100px;
line-height: 100px;
background-color: #4f81bd;
}
</style>
App.vue文件:
javascript
<template>
<my-header></my-header>
<my-main></my-main>
<my-footer></my-footer>
</template>
<script setup>
import MyHeader from './components2/MyHeader.vue';
import MyMain from './components2/MyMain.vue';
import MyFooter from './components2/MyFooter.vue';
</script>
<style>
* {
margin: 0;
}
#app {
height: 100vh;
padding: 10px;
background: skyblue;
font-size: 30px;
color: #fff;
text-align: center;
}
</style>
五、组件的全局注册
全局注册的组件,在项目的任何组件中都能使用
1. 步骤
- 创建
.vue组件(三个组成部分) main.js中进行全局注册
2. 使用组件(与局部组件一样)
当成 HTML 标签直接使用:
- 双标签:
<组件名></组件名> - 自闭合的单标签:
<组件名 />
3. 注意
组件名规范:大驼峰命名法(推荐) 或 烤串法 ,如 MyHeader 或 my-header。
4. 语法
在 main.js 中通过导入组件,并且使用 app.component() 方法注册组件:
javascript
// main.js文件
import MyPanel from './components/MyPanel.vue'
// 注册全局组件语法:
// app.component('组件名', 组件对象)
// 大驼峰组件名(更推荐这种,因为使用标签时候既可以用大驼峰,也可以用烤串法)
app.component('MyPanel', MyPanel)
// 烤串法组件名(需要注意:使用标签时候,只能用烤串法,而不能再用大驼峰了)
app.component('my-panel', MyPanel)
注意,上面代码中的 app 对象,是 createApp(App) 得到的应用对象!
5. 练习
components3/MyButton.vue文件:
javascript
<script setup></script>
<template>
<button class="my-button">通用按钮</button>
</template>
<style scoped>
.my-button {
height: 50px;
line-height: 50px;
padding: 0 15px;
background-color: #3bae56;
border-radius: 5px;
font-size: 16px;
color: white;
border: none;
cursor: pointer;
}
</style>
在 main.js 中,导入并全局注册:
javascript
import { createApp } from 'vue'
import App from './App.vue'
import MyButton from './components3/MyButton.vue'
const app = createApp(App) // 拿到应用对象
app.component("MyButton", MyButton)
app.mount('#app') // 最后再去挂载即可
components3/MyHeader.vue文件:
javascript
<script setup></script>
<template>
<div class="my-header">
我是my-header
<my-button />
</div>
</template>
<style>
.my-header {
height: 100px;
line-height: 100px;
background-color: #8064a2;
}
</style>
components3/MyMain.vue文件:
javascript
<script setup></script>
<template>
<div class="my-main">
我是my-main
<my-button />
</div>
</template>
<style>
.my-main {
height: 400px;
margin: 20px 0;
line-height: 400px;
background-color: #f79646;
}
</style>
components3/MyFooter.vue文件:
javascript
<script setup></script>
<template>
<div class="my-footer">
我是my-footer
<my-button />
</div>
</template>
<style>
.my-footer {
height: 100px;
line-height: 100px;
background-color: #4f81bd;
}
</style>
App.vue文件:
javascript
<template>
<my-header></my-header>
<my-main></my-main>
<my-footer></my-footer>
</template>
<script setup>
import MyHeader from './components3/MyHeader.vue';
import MyMain from './components3/MyMain.vue';
import MyFooter from './components3/MyFooter.vue';
</script>
<style>
* {
margin: 0;
}
#app {
height: 100vh;
padding: 10px;
background: skyblue;
font-size: 30px;
color: #fff;
text-align: center;
}
</style>
