引入
Vue2的组件中,数据是写在data里面,方法写在methods里。这样子在小型的组件中是很清晰的,但是当在大型组件中,数据跟方法就会多起来,而数据与其相关联的方法就会被其他数据和方法分隔的很远,往往很难被看出它们之间的关联。因此,Vue3中就有了合成api来解决这个问题,帮助我们将有关联的数据与方法囊括起来。
setup在vue的生命周期
setup在vue的生命周期中是比 beforeCreate 还要早执行的
用法
在vue3组件中的 setup 选项使用 Composition API
setup 是一个函数,它会在创建组件之前执行 props ,也就是说,setup 执行时尚未创建组件实例,因此选项 this
内部没有任何内容 setup 。这意味着,除了 props ,你将无法访问组件中声明的任何属性-本地状态,计算属性或方法。
export default {
components: {
RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props:{
user:{
type:String }
},
setup(props) {
console.log(props) // { user:'' }
return {
}
}
}
它跟 data 类似,都是返回组件中用到的函数或者方法
一个计数的例子
vue2写法
<template>
<div>
<h1 @click="changeEvent"> 计数:{
{
count}} </h1>
</div>
</template>
<script>
export default{
name:'App',
data(){
return{
count:0
}
},
methods:{
changeEvent(){
this.count++
}
}
}
</script>
vue3的 setup 写法
ref
setup里面的基本类型变成是响应式的使用,就要把数据写在ref中
<template>
<div>
<h1 @click="changeEvent"> 计数:{
{
count}} </h1>
</div>
</template>
<script>
import {
ref } from 'vue'
export default{
name:'App',
data(){
return{
}
},
setup(){
// 要放到 ref 里面才会是响应式的
const count = ref(0)
function changeEvent(){
// 在这里获取 count 的值是保存到了 count.value 里的
count.value++
}
return {
count,
changeEvent
}
}
}
</script>
reactive和toRefs
setup里面的对象要响应式,使用reactive
像ref一样使用reactive,通过toRef进行转换
<template>
<div>
<!-- ref的方式 -->
<h1 @click="changeEvent"> 计数:{
{
count}} </h1>
<!-- reactive的方式 -->
<h1>用户名:{
{
user.username}}</h1>
<!-- toRefs的方式 -->
<h1 @click="changeUsername">用户名:{
{
username}}</h1>
</div>
</template>
<script>
import {
ref,reactive,toRefs } from 'vue'
export default{
name:'App',
data(){
return{
}
},
setup(){
// 要放到 ref 里面才会是响应式的
const count = ref(0)
function changeEvent(){
// 在这里获取 count 的值是保存到了 count.value 里的
count.value++
}
const user = reactive({
username:'ayaan',
age:18,
type:'帅'
})
function changeUsername(){
user.username = 'abc'
}
return {
count,
changeEvent,
user,
...toRefs(user),
changeUsername
}
}
}
</script>
computed、watch、watchEffect
这是setup里面的computed和watch,它们的作用和外面的computed和watch是一样的
watchEffect其实就是自动监听回调函数里面的数据改变而触发执行,而watch就是要指定监听的数据
例子:利用computed翻转username,利用watchEffect监听age改变
<template>
<div>
<!-- ref的方式 -->
<h1 @click="changeEvent"> 计数:{
{
count}} </h1>
<!-- reactive的方式 -->
<h1>用户名:{
{
user.username}}</h1>
<!-- toRefs的方式 -->
<h1 @click="changeUsername">用户名:{
{
username}}</h1>
<h1>翻转用户名:{
{
user.reverseUsername}}</h1>
</div>
</template>
<script>
import {
ref,reactive,toRefs,computed,watch,watchEffect } from 'vue'
export default{
name:'App',
data(){
return{
}
},
setup(){
// 要放到 ref 里面才会是响应式的
const count = ref(0)
function changeEvent(){
// 在这里获取 count 的值是保存到了 count.value 里的
count.value++
}
const user = reactive({
username:'ayaan',
reverseUsername:computed(()=>{
return user.username.split('').reverse().join('')
})
age:18,
type:'帅'
})
function changeUsername(){
user.username = 'abc'
}
//watchEffect回调函数里面用到了那些数据,那些数据发生改变就会触发这个回调函数
watchEffect(()=>{
console.log(user.age)
console.log('当user.age发生改变时候就会执行这里')
})
//watch监听单个数据改变,例如下面监听count改变
watch(count,(newValue,preValue)=>{
console.log(newValue,preValue)
console.log('当count发生改变时候就会执行这里')
})
//watch监听多个数据改变,例如下面监听count改变
watch([count,user],(newValue,preValue)=>{
console.log(newValue,preValue)
console.log('当count或者user发生改变时候就会执行这里')
})
return {
count,
changeEvent,
user,
...toRefs(user),
changeUsername
}
}
}
</script>
setup中访问props的数据
setup函数本身会传入props参数和content参数,但是外层的props选项也不能省略
import {
ref } from 'vue'
<template>
<div>
<!-- props的方式 -->
<h1>用户名:{
{
username}}</h1>
<h1>描述:{
{
description}}</h1>
</div>
</template>
<script>
export default{
name:'App',
data(){
return{
}
},
setup(props,content){
console.log(props)
const description = ref(props.username)
return{
description
}
},
props:['username']
}
content的内容结构如下,它可以获取到父组件传递过来的属性等数据,比如这里的class属性
setup里面可以用到的生命周期
除了beforeCreate,和created之外都有
它们分别是onBeforeMount,onMounted,onBeforeUpdate,onBeforeUnmount,onUnmounted
import {
ref,onBeforeMount,onMounted,onBeforeUpdate,onBeforeUnmount,onUnmounted } from 'vue'
<template>
<div>
<!-- props的方式 -->
<h1>用户名:{
{
username}}</h1>
<h1>描述:{
{
description}}</h1>
</div>
</template>
<script>
export default{
name:'App',
data(){
return{
}
},
setup(props,content){
console.log(props)
const description = ref(props.username)
onBeforeMount(()=>{
console.log('beforeMount')
})
//那个变量和生命周期息息相关的话可以写在一起附近
onBeforeMount(()=>{
console.log('可以使用多次onBeforeMount')
})
return{
description
}
},
props:['username']
}
通过Provide和inject将数据提供给子组件
除了使用props
传值之外,还可以使用provide
(提供)和inject
(注入)将数据提供给子组件。
import {
ref,reactive,provide } from 'vue'
<template>
<div>
<Student />
</div>
</template>
<script>
import Student from './components/Student.vue'
export default{
name:'App',
components:{
Student }
data(){
return{
}
},
setup(props,content){
// 提供数据
const student = reactive({
name:'小红',
className:'三年6班'
})
// provide的参数是 key,value 的形式
provide('student',student)
return{
}
}
}
Student子组件内容
import {
ref,reactive,inject } from 'vue'
<template>
<div>
<h1>学生名:{
{
name}}</h1>
<h1>班级:{
{
className}}</h1>
</div>
</template>
<script>
export default{
name:'Student',
data(){
return{
}
},
setup(props,content){
const student = reject('student')
return{
...student
}
}
}