# 一、生命周期图示
# 1、vue2 回顾
# 2、对比图 1
- 对比图 1 (选项式 vue3、vue2)
# 3、对比图 2
- 对比图 2 (选项式 vue3、组合式 vue3)
# 二、setup()钩子
setup() 自身并不含对组件实例的访问权,即在 setup() 中访问 this 会是 undefined。
你可以在选项式 API 中访问组合式 API 暴露的值,但反过来则不行。
使用示例
<script>
const { createApp, ref, onMounted } = Vue
createApp({
setup() {
const count = ref(1)
onMounted(() => {
console.log('setup中:', this) // window
// setup() 自身并不含对组件实例的访问权
console.log('setup中:', this.message) // undefined
})
return {
count
}
},
data() {
return {
message: '欢迎访问!'
}
},
mounted() {
console.log(this) // {count: 1, message: "欢迎访问!"}
// 可以在选项式 API 中访问组合式 API 暴露的值
console.log(this.count)
}
}).mount('#app')
</script>
setup() 应该同步地返回一个对象。唯一可以使用 async setup() 的情况是,该组件是 Suspense (opens new window) 内置组件的后裔。
<script>
const { createApp, ref } = Vue
createApp({
// warning:setup function returned a promise
async setup() {
//
}
}).mount('#app')
</script>
# 1、使用示例
下面简单看看,在 setup 中使用生命周期钩子和通过配置项使用生命周期钩子的区别:
<script>
import { onMounted } from 'vue'
export default {
setup() {
console.log('---setup---')
// 生命周期钩子(回调形式)
onMounted(() => {
console.log('---onMounted---')
})
},
// 生命周期函数(函数形式)
mounted() {
console.log('---mounted---')
}
}
</script>
---setup---
---onMounted---
---mounted---
当然,在 setup 中使用生命周期钩子是也要有一些注意事项:
# 2、注意事项 ✨
setup 中是没有 onBeforeCreate、onCreated 钩子的。因为 setup 是围绕这俩的生命周期钩子运行的,所以不需要显示的定义,直接在 setup 函数中编辑即可。
vue3 中,beforeDestroy、destroyed 被改名为 beforeUnmount、unmounted
选项式 API | 组合式 setup | |
---|---|---|
beforeCreate | → → → | |
created | → → → | |
beforeMount | → → → | onBeforeMount |
mounted | → → → | onMounted |
beforeUpdate | → → → | onBeforeUpdate |
updated | → → → | onUpdated |
beforeUnmount | → → → | onBeforeUnmount |
unmounted | → → → | onUnmounted |
setup 中除了有 vue2 中常见的钩子,还有其他组合式生命周期钩子 (opens new window)
完整使用案例
反正后面要将单文件组件,这里就先用一下吧:
- App.vue
<template>
<button @click="isShow = !isShow">创建与销毁组件</button>
<Demo v-if="isShow"></Demo>
</template>
<script>
import Demo from './components/Demo.vue'
import { ref } from 'vue'
export default {
name: 'App',
components: {
Demo
},
setup() {
let isShow = ref(true)
return {
isShow
}
}
}
</script>
- Demo.vue
<template>
<div></div>
</template>
<script>
import { onUnmounted } from 'vue'
export default {
name: 'Demo',
setup() {
// 对应的
onUnmounted(() => {
console.log('---onUnmounted---')
})
// 额外的
// onActivated()
// ……
},
// 1、setup中没有
created() {
console.log('---created---')
},
// 2、注意名称变化
unmounted() {
console.log('---unmounted---')
}
}
</script>
<style scoped>
div {
width: 300px;
height: 200px;
background: skyblue;
}
</style>
# 3、setup 参数 🎈
在 setup 中无法使用 this,那我们怎么使用 props、emit……?
答案:使用 setup 参数
- props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
- context:上下文对象,具体内容如下:
属性 作用 attrs 组件外部传递过来,但没有在 props 配置中声明的属性 相当于 this.$attrs
slots 收到的插槽内容 相当于 this.$slots
emit 分发自定义事件的函数 相当于 this.$emit
<script>
import { reactive } from 'vue'
export default {
props: ['msg', 'school'],
// 这个😒(还要声明一下,不然有warning)
emits: ['hello'],
setup(props, context) {
// 1、props参数
console.log(props)
// 2、context参数
console.log(context)
}
}
</script>
# 4、拓展:依赖注入
在上面的生命周期中我们已经接触到了 props 可以通过 setup 参数逐级透传,形成数据传递流。
同 vue2 一样,在 vue3 中应该也有 provide 和 inject 供我们使用:
vue2 中的依赖注入
<script>
export default {
// provide 提供给后代✨组件的数据/方法
// provide: {
// message: 'provided by father'
// }
provide() {
return {
message: 'provided by father'
}
}
}
</script>
<script>
export default {
// 使用 inject 选项来接收由provide提供的、当前组件✨需要的数据/方法
inject: ['message']
}
</script>
<script>
import { provide } from 'vue'
export default {
setup() {
provide('name', 'lencamo')
// vue3可以极简的解决provide的响应式问题
const age = ref(22) // 采用响应式API即可
provide('age', age)
}
}
</script>
<script>
import { inject } from 'vue'
export default {
setup() {
// 在inject中还可以设置默认值
const name = inject('name', 'lihua')
const age = inject('age')
}
}
</script>