这一节了解一下Vue3中的组件进阶,组件在被创建出来到渲染完成会经历一系列过程,同样组件的销毁也会经历一系列过程,组件从创建到销毁的这一系列过程被称为组件生命周期,生命周期的节点被定义一系列方法,也被称为生命周期钩子。简单总结:
API
- beforeCreate
含义:组件实例刚创建,数据、方法都未初始化 作用:几乎不用,不能操作 this 数据
javascript
<script>
export default {
beforeCreate() {
console.log('组件即将创建')
}
}
</script>
- created
含义:组件创建完成,数据 / 方法已初始化,但未生成 DOM 作用:请求接口、初始化数据、定时器
javascript
<script>
export default {
data(){return {list:[]}},
created(){
console.log('组件创建完毕,可请求数据')
}
}
</script>
- beforeMount
含义:挂载 DOM 之前 作用:挂载前最后一次修改模板数据
javascript
<script>
export default {
beforeMount(){
console.log('即将渲染DOM')
}
}
</script>
- mounted 最常用
含义:DOM 已渲染挂载完成 作用:操作 DOM、初始化插件、开启定时器、请求数据
javascript
<template><view>我是组件</view></template>
<script>
export default {
mounted(){
console.log('DOM已挂载完毕')
}
}
</script>
- beforeUpdate
含义:数据变化,视图重新渲染前 作用:更新前获取旧 DOM 状态
javascript
<script>
export default {
beforeUpdate(){
console.log('视图即将更新')
}
}
</script>
- updated
含义:视图更新完成 作用:更新后操作 DOM
javascript
<script>
export default {
updated(){
console.log('视图已更新')
}
}
</script>
- beforeUnmount
含义:组件销毁前 作用:清除定时器、移除监听
javascript
<script>
export default {
beforeUnmount(){
clearInterval(this.timer)
}
}
</script>
- unmounted
含义:组件完全销毁 作用:收尾清理工作
javascript
<script>
export default {
unmounted(){
console.log('组件已销毁')
}
}
</script>
- props 类型校验
含义:限制传入参数类型 作用:规范传参、控制台报错提示
javascript
<script>
export default {
props:{
name:String,
age:Number
}
}
</script>
- props required
含义:强制必须传参 作用:保证组件必备参数
javascript
<script>
export default {
props:{
title:{
type:String,
required:true
}
}
}
</script>
- props default 默认值
含义:未传参时使用默认值 作用:防止报错、给默认展示
javascript
<script>
export default {
props:{
msg:{
type:String,
default:'默认提示'
}
}
}
</script>
- props validator 自定义校验
含义:自定义规则校验参数 作用:范围、格式限制
javascript
<script>
export default {
props:{
score:{
validator(val){
return val>=0 && val<=100
}
}
}
}
</script>
- props 单向只读
含义:子组件不能修改 props 作用:遵循单向数据流,避免数据混乱
javascript
<template>
<view>{{ title }}</view>
</template>
<script>
export default {
props:['title'],
methods:{
change(){
// 错误:不能修改 props
// this.title = 'xxx'
}
}
}
</script>
- 局部 Mixin
含义:抽取公共逻辑复用 作用:复用生命周期、方法、数据
javascript
<script>
// 定义混入
const myMixin = {
created(){console.log('mixin 加载')}
}
export default {
mixins:[myMixin]
}
</script>
- 全局 Mixin
含义:所有组件自动混入 作用:全局公共逻辑
javascript
import { createApp } from 'vue'
const app = createApp()
app.mixin({
mounted(){console.log('每个组件都触发')}
})
- Mixin 合并规则
含义:生命周期先执行 mixin 再组件;选项以组件优先 作用:理解覆盖逻辑
javascript
<script>
const m = { mounted(){console.log('mixin')}}
export default {
mixins:[m],
mounted(){console.log('组件自身')}
}
</script>
- 局部自定义指令
含义:封装 DOM 操作逻辑 作用:自动聚焦、权限按钮
javascript
<template>
<input v-focus />
</template>
<script>
export default {
directives:{
focus:{
mounted(el){el.focus()}
}
}
}
</script>
- 全局自定义指令
含义:全局所有组件可用
javascript
app.directive('focus',{
mounted(el){el.focus()}
})
- 指令传参
含义:指令可传递参数、修饰符 作用:灵活配置指令行为
javascript
<template>
<view v-color="red">文字</view>
</template>
<script>
export default {
directives:{
color:{
mounted(el,binding){
el.style.color = binding.value
}
}
}
}
</script>
- provide 提供
含义:父 / 祖先向下提供数据 作用:多层嵌套不用逐层 props
javascript
<script setup>
import { provide } from 'vue'
provide('appName','Vue3项目')
</script>
- inject 注入
含义:后代组件接收数据 作用:跨层级取值
javascript
<script setup>
import { inject } from 'vue'
const name = inject('appName')
</script>
- Teleport
含义:将组件 DOM 传送到指定节点 作用:弹窗、浮层不受父样式嵌套影响
javascript
<template>
<teleport to="body">
<view class="mask">我是全局弹窗</view>
</teleport>
</template>
<style>
.mask{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);}
</style>
栗子:
javascript
<template>
<view class="container">
<button @click="showLife = !showLife">显示/隐藏生命周期组件</button>
<view v-if="showLife">
<LifeDemo />
</view>
<PropsDemo title="我是标题" :score="88" />
<view class="mt20">
<input v-focus placeholder="进入页面自动聚焦" class="input" />
</view>
<InjectDemo />
<button @click="showModal = true" class="mt20">打开Teleport弹窗</button>
<teleport to="body">
<view v-if="showModal" class="mask">
<view class="modal-box">
<text>全局弹窗,不受父样式限制</text>
<button @click="showModal = false" class="mt20">关闭</button>
</view>
</view>
</teleport>
</view>
</template>
<script setup>
import { ref, provide } from 'vue'
// 控制生命周期组件显示
const showLife = ref(true)
const showModal = ref(false)
const LifeDemo = {
created() {
console.log('1.created 组件创建完成')
},
mounted() {
console.log('2.mounted DOM挂载完毕')
},
beforeUnmount() {
console.log('3.beforeUnmount 准备销毁')
},
unmounted() {
console.log('4.unmounted 组件已销毁')
},
template: '<view class="mt20">生命周期组件</view>'
}
const PropsDemo = {
props: {
title: {
type: String,
default: '默认标题'
},
score: {
type: Number,
validator: val => val >= 0 && val <= 100
}
},
template: '<view class="mt20">标题:{{title}} 分数:{{score}}</view>'
}
const directives = {
focus: {
mounted(el) {
// 自动聚焦
el.focus()
}
}
}
const myMixin = {
created() {
console.log('Mixin 公共逻辑执行')
}
}
provide('appInfo', {
name: 'Vue3进阶项目',
version: '2.0'
})
const InjectDemo = {
inject: ['appInfo'],
template: '<view class="mt20">项目名称:{{appInfo.name}}</view>'
}
</script>
<style scoped>
.container {
padding: 30rpx;
}
.mt20 {
margin-top: 20rpx;
}
.input {
border: 1rpx solid #eee;
padding: 20rpx;
border-radius: 10rpx;
}
.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
}
.modal-box {
background: #fff;
padding: 40rpx;
border-radius: 15rpx;
}
</style>