Vue组件
# Vue组件
# 介绍
Vue组件是可复用、独立的单元,它把模板、逻辑和样式封装在一起,使得大型应用可以像搭积木一样组织和维护。每个组件只负责一种UI或业务功能,保持代码简洁。
# 单文件式组件
单文件组件是Vue框架使用的一种组织Vue组件的方式。它将组件的逻辑(JavaScript),模板(HTML)和样式(CSS)封装在同一个.vue文件里,形成一个独立、可复用的功能块。
<!-- 组件的HTML结构视图结构的模板 -->
<template>
...
</template>
<!-- 组件的业务逻辑、状态和生命周期,组合式API/选项式API -->
<script>
...
</script>
<!-- 组件的局部样式,使用scoped可实现局部作用域,防止样式泄漏 -->
<style scoped>
...
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
# 单页应用
单页应用(SFC)是Vue.js框架的一种Web应用模式。它的核心特征是整个应用只有一个HTML页面,在首次加载时把必要的HTML、CSS、JavaScript资源一次性下载到浏览器,随后所有的页面切换、内容更新都通过前端路由和组件的动态渲染完成,不再进行整页刷新。
比如一个应用有注册、登录、管理等功能,单页应用就是将这些功能全都在一个页面中动态渲染实现,而非跳转。
# 组件的分类
| 分类 | 说明 | 典型场景 |
|---|---|---|
| 全局组件 | 通过 app.component('MyComp', {...}) 注册后,整个应用都能直接使用 <my-comp>。 | 常用的 UI 基础组件(按钮、弹窗、表格等)。 |
| 局部组件 | 在父组件的 components 选项中声明,仅在该父组件内部可用。 | 业务页面内部的子模块、复用度不高的功能块。 |
| 函数式组件 | 没有内部状态(data)和生命周期,仅返回渲染结果,渲染开销更低。 | 纯展示、渲染大量列表的轻量组件。 |
| 异步组件 | 使用 defineAsyncComponent 按需加载,减小首屏体积。 | 大型页面的次要模块、路由懒加载。 |
# 组件使用例子
html文件内使用方式,一般只在简单页面或测试时使用。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue测试页面</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用自定义组件,并传入初始值 -->
<my-counter :initial="3"></my-counter>
</div>
<script>
// 导入createApp、ref
const {createApp, ref} = Vue
// 定义自定义组件
const MyCounter = {
// 组件模板
template: `
<div>
<p>当前计数:{{ count }}</p>
<button @click="count++">+1</button>
<button @click="count--">-1</button>
</div>
`,
// 接收父组件传来的属性
props: {
initial: {
type: Number,
default: 0
}
},
// 组件逻辑入口
setup(props) {
const count = ref(props.initial);
return {
count
};
}
};
// 创建Vue应用实例,根组件为空
const app = createApp({});
// Vue应用中注册全局组件,传入组件名和组件对象
app.component('my-counter', MyCounter)
// 挂载应用到标签
app.mount('#app')
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 组件生命周期
# 介绍
Vue组件在 创建 → 挂载 → 更新 → 销毁四大阶段会依次触发一系列钩子函数,开发者可以在对应时机执行自定义逻辑。
Vue 2选项式和Vue 3选项式和Vue 3组合式三者的生命周期钩子函数都略有不用。
# Vue2选项式
| 阶段 | 钩子 | 触发时机 |
|---|---|---|
| 创建 | beforeCreate | 初始化前 |
created | 初始化后 | |
| 挂载 | beforeMount | 挂载前,虚拟DOM生成但未插入真实DOM |
mounted | 挂载后 | |
| 更新 | beforeUpdate | 更新前 |
updated | 更新后 | |
| 销毁 | beforeDestroy | 销毁前 |
destroyed | 销毁后 |
# Vue3选项式
与Vue 2 基本保持一致。
| 阶段 | 钩子 | 触发时机 |
|---|---|---|
| 创建 | beforeCreate | 初始化前 |
created | 初始化后 | |
| 挂载 | beforeMount | 挂载前 |
mounted | 挂载后 | |
| 更新 | beforeUpdate | 更新前 |
updated | 更新后 | |
| 销毁 | beforeUnmount | 销毁前 |
unmounted | 销毁后 |
# Vue3组合式
通过 import { onMounted, onUnmounted, ... } from 'vue' 导入,并在 setup() 中定义使用即可。
| 阶段 | 钩子 | 触发时机 |
|---|---|---|
| 创建 | 由 setup 代替 | 初始化前 |
由 setup 代替 | 初始化后 | |
| 挂载 | onBeforeMount | 挂载前 |
onMounted | 挂载后 | |
| 更新 | onBeforeUpdate | 更新前 |
onUpdated | 更新后 | |
| 销毁 | onBeforeUnmount | 销毁前 |
onUnmounted | 销毁后 |
setup() {
// 在setup中定义使用即可
onMounted(() => {...})
...
}
2
3
4
5
# 动态组件
动态组件指可以根据条件动态切换渲染的组件,常用于标签页切换、表单步骤切换、路由视图切换等场景。
格式:
<component :is="组件对象/组件名变量"></component>我们也可以使用v-if来实现,但使用component标签切换组件更加方便简洁。
<!-- 实现通过变量名来动态切换组件进行渲染 -->
<component :is="current_comp"></component>
2
# keep-alive
keep-alive用于缓存组件实例,被<keep-alive>标签包裹的动态组件在切换时不会被销毁,而是将其保留在内存中,下一次切回时直接复用。
它可以保持组件内部状态(data、表单输入、滚动位置等)。同时可以省去组件的重新创建、渲染和数据请求,以降低CPU与网络开销,提升用户体验。
<!-- 所有组件都缓存 -->
<keep-alive>
<component :is="current_comp"></component>
</keep-alive>
<!-- 只缓存PageA组件 -->
<keep-alive include="PageA">
<component :is="current_comp"></component>
</keep-alive>
2
3
4
5
6
7
8
9
keep-alive标签还支持细粒度的缓存管理,通过以下几个控制属性:
include:只缓存匹配的组件名,可传入字符串、正则或数组,字符串指定多个时用逗号隔开。exclude:排除不需要缓存的组件名,可传入字符串、正则或数组,字符串指定多个时用逗号隔开。max:限制组件缓存数量,超出时会按照LRU(最近最少使用)策略淘汰最旧的实例。
# 插槽
插槽是Vue为组件提供的内容分发机制,它让父组件可以把任意HTML结构或子组件传递到子组件内部的预留位置。通过插槽,子组件可以只负责布局和功能,具体的展示内容由使用它的父组件决定。
默认插槽使用
在父组件模板中的子组件标签内部书写要传入的内容,然后在子组件模板中使用<slot></slot>标签,Vue会将slot标签替换成传进的内容。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue测试页面</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<my-counter>
<p>我会被传到哪儿呢?</p>
</my-counter>
</div>
<script>
const {createApp, ref} = Vue
const MyCounter = {
template: `
<div>
<h1>我是顶</h1>
<slot>会传到这儿,该标签会被替换传入的内容</slot>
<h1>我是底</h1>
</div>
`,
setup() {
return {};
}
};
const app = createApp({});
app.component('my-counter', MyCounter)
app.mount('#app')
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
具名插槽使用
在父组件模板中的子组件标签内部中使用template标签并以 #名称 或 v-slot:名称 指定具体名称,然后在标签内部书写要传入的内容。最后在子组件模板中使用<slot name="名称"></slot>标签即可,Vue会将slot标签替换成对应名称的标签。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue测试页面</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<my-counter>
<template #content01>我是content01</template>
<template #content02>我是content02</template>
</my-counter>
</div>
<script>
const {createApp, ref} = Vue
const MyCounter = {
template: `
<div>
<h1>我是顶</h1>
<slot name="content02"></slot>
<h1>我是底</h1>
<slot name="content01"></slot>
</div>
`,
setup() {
return {};
}
};
const app = createApp({});
app.component('my-counter', MyCounter)
app.mount('#app')
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35