Composition API
setup
setup
函数是Composition API(组合API)
的入口。
setup
执行时机是在beforeCreate
之前执行。
在setup
函数中定义的变量和方法最后都是需要return
出去的,不然无法在模板中使用。
在setup
里面是不会用到this
的。
setup
中接收的props
是响应式的,当传入新的props
时,会及时被更新。由于是响应式的,所以不可以使用ES6解构
,解构会消除它的响应式的。setup
接收的context
中提供了最常用的四个属性:attrs
、slot
和emit
,分别对应Vue@2.x
中的$attr
属性、slot
插槽、$emit
发射事件和expose
暴露标记。并且这四个属性都是自动同步最新的值,所以我们每次使用拿到的都是最新值。
expose
:在传统的写法中,可以在父组件中,通过ref
实例的方式去访问子组件的内容,但在<script setup>
中,setup
相当于一个闭包,除了内部的template
模板,都无法访问内部的数据和方法。如果需要对外暴露setup
中的数据和方法,需要使用此属性。
<template>
<h1>App</h1>
<h2>{
{ age }}</h2>
</template>
<script>
import {
defineComponent, ref } from "vue"
export default defineComponent({
name: 'App',
props: {
name: String
},
setup(props, context) {
let age = ref(18)
function say() {
console.log(`我${
age.value}`)
}
//返回一个对象
return {
age,
say
}
}
})
</script>
如果上面这种return
的写法不喜欢的话,可以用新的语法糖<script setup>
,<script setup>
就相当于在编译运行时把代码放到setup
函数中运行,然后把导出的变量定义到上下文中,并包含在返回的对象中。
在<script setup>
中,引入的组件可以直接使用,无需再通过components
进行注册,并且无法指定当前组件的名字,它会自动以文件名为主,也就无需再写name
属性。
使用props
通过defineProps
指定当前props
类型,获得上下文的props
对象。
使用emits
使用defineEmits
定义当前组件含有的事件,并通过返回的上下文去执行emit
。
使用slots
和attrs
在<script setup>
中使用slots
和attrs
,分别使用useSlots
和useAttrs
帮助函数。
使用expose
使用defineExpose
暴露需要对外的数据和方法。
<template>
<Child />
</template>
<script setup>
import Child from './Child.vue'
import {
ref, defineEmits, defineExpose, defineProps, useSlots, useAttrs } from 'vue'
let age = ref(18)
const props = defineProps({
name: String
})
const emits = defineEmits(['add', 'delete')
const slots = useSlots()
const attrs = useAttrs()
defineExpose({
age,
say
})
const say = () => {
console.log(`我${
age.value}`)
}
</script>
从
Vue@2.6.x
开始,Vue 为具名和范围插槽引入了一个全新的语法,即v-slot
指令。目的就是想统一slot
和scope-slot
语法,使代码更加规范和清晰。在vue@3.x
中,只能使用v-slot
。
reactive
、ref
、toRefs
和toRef
在vue@3.x
使用reactive
和ref
来进行响应式数据定义。
ref
使用ref
定义的变量变成了对象,并且还是RefImpl
的实例对象。所以在修改的时候要用.value
去修改,因为内部是按照get
和set
去修改页面的。但是在template
中就不用自己手动添加.value
,因为vue@3.x
在检测到是ref
对象,就自动添加了.value
。如果用ref
定义对象,则不再是RefImpl
实例对象,变成了Proxy
实例对象,因为在vue@3.x
底层,如果是对象,就变成Proxy
实例对象,对于基本数据类型就按照Object.defineProperty
里面的get
和set
进行数据劫持然后进行响应式,但是如果是对象类型的话,是用Proxy
,就相当于,ref
中是对象,自动会调用reactive
。
reactive
reactive
只能定义对象类型的响应式数据,把Object
转换为Proxy
,进行一个深层次的响应式,也可以进行数组的响应式。
ref
与reactive
的区别
ref
用来定义基本数据类型
,也可以定义对象或数组,知识内部自动调用了reactive
来转换。ref
通过Object.defineProperty()
的get
与set
来实现响应式(数据劫持)。ref
定义的数据:操作数据需要.value
,读取数据时模板中直接读取不需要.value
。reactive
用来定义:对象或数组类型数据
。reactive
通过使用Proxy
来实现响应式(数据代理),并通过Reflect
操作源代码内部的数据。reactive
定义的数据:操作和读取数据均不需要.value
。
toRefs
toRefs
用于将一个reactiv