对于任何包含响应式数据的复杂逻辑,都应该使用计算属性。
在前面的Options API
(选项式API
)中,是使用computed
选项来完成计算属性的定义。
在Composition API
(组合式API
)中,我们可以在setup
函数中使用computed
方法来编写一个计算属性。
setup中如何使用computed:
接收一个getter
函数,并为getter
函数返回的值,返回一个不变的ref
对象。
{{ fullname }}
可以看到注意点有两个:
computed
才能够在setup
函数中使用.value
属性,因为它是一个ref
对象
{{ bottomInfo.content }}
接收一个具有get
和set
的对象,返回一个可变的(可读写)ref
对象。
{{ fullname }}
在组合式AP
I中,可以使用watchEffect
和watch
来完成响应式数据的侦听:
watchEffect
:用于自动收集响应式数据的依赖
watch
:需要手动指定侦听的数据源,数据变化时执行其回调函数
默认情况下它是惰性的,只有当被侦听的源发生变化时才会执行回调
const info = reactive({
name: "why",
age: 18,
friend: {
name: "kobe"
}
})
watch(info, (newValue, oldValue) => {
console.log(newValue, oldValue)
})
const info = reactive({
name: "why",
age: 18,
friend: {
name: "kobe"
}
})
const message = ref("Hello watch");
watch([info, message], (newValue, oldValue) => {
console.log(newValue, oldValue)
})
默认情况下,组合式API
中的watch
函数就已经帮我们进行深度监听了。
当然也可以选择传入deep
显式指定。
而立即执行则需要传入immediate
显式指定。
const info = reactive({
name: "why",
age: 18,
friend: {
name: "kobe"
}
})
watch(info, (newValue, oldValue) => {
console.log(newValue, oldValue)
},{
immediate: true,
deep: true
})
当监听到某些响应式数据变化时,我们希望执行某些操作,这个时候可以使用watchEffect
。
首先,watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖; 其次,只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行
有时希望可以让watchEffect
停止侦听。此时可以获取watchEffect
的返回值函数,调用该函数即可。
watch
必须制定数据源, watchEffect
自动收集依赖watch
监听到改变, 可以拿到改变前后value,watchEffect
只能拿到变化后的watchEffect
默认直接执行一次,watch
在不设置immediate
第一次是不执行上一篇已经说过了如何使用ref
函数去定义响应式数据。
而Vue2.x
中的有一个通过ref
属性去获取DOM
元素或者组件。这在Vue3.x
的setup
函数中又是怎么做到的呢?
setup
函数中的方式是定义一个ref
对象,绑定到元素或者组件的ref
属性上即可。
使用起来就是先引入,然后在setup
函数中进行使用,需要接收一个函数对象,一般就要箭头函数。
API
和组合式API
的对应关系选项式API | setup中对应的组合式API |
---|---|
beforecreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeupdate | onBeforeupdate |
updated | onupdated |
beforeunmount | onBeforeunmount |
unmounted | onUnmounted |
activated | onActivated |
deactivated | onDeactivated |
因为setup
是围绕beforecreate
和created
生命周期钩子运行的,所以不需要显式地定义它们。
因此在这些钩子中编写的任何代码都可以直接在setup
函数中编写。
provide
函数可以传入两个参数:
name:提供的属性名称;
value:提供的属性值
const name = ref("张三")
provide("name", name)
provide("age", 18)
为了增加 provide
值和 inject
值之间的响应性,我们可以在provide
值时使用ref
和reactive
。
就想这里的age
就不具备响应式。
在后代组件中可以通过inject
函数来注入需要的属性和对应的值.
Inject
函数可以传入两个参数(可以只传其一):
要注入的属性的名称;
注入属性不存在时的默认值;
const name = inject("name")
const age = inject("age", 0)
对于复杂数据的传共享,都会使用
Vuex
或者pinia
去共享数据。大部分情况不会去使用依赖注入的方式
语法的优势当打算把所有的内容都写在setup
函数中时,可以使用语法。
是在单文件组件 (
SFC
) 中使用组合式 API
的编译时语法糖。
当同时使用SFC
与组合式API
时则推荐该语法,他有如下特点:
更少的样板内容,更简洁的代码
能够使用纯 Typescript
声明 prop
和抛出事件
更好的运行时性能
更好的IDE
类型推断性能
AppContent: {{ message }}
注意点:
如何使用?
将 setup
属性 添加到 标签上。里面的代码会被编译成组件
setup()
函数的内容。
这意味着与普通的
使用setup
语法糖时,提供了defineProps()
函数去定义props
。
ShowInfo: {{ name }}-{{ age }}
defineProps()
函数的返回值是一个只读属性,只能使用,不能修改。
使用setup
语法糖时,提供了defineEmits()
函数去发出事件,从而给父元素传递一些信息。
使用的组件内容是不公开的。
意思就是在父组件中的模板ref
或者$parent
链获取到的组件的公开实例。
不会暴露任何在中声明的属性或者方法。
通过defineExpose
编译器宏来显式指定在组件中要暴露出去的属性或者方法。
子组件:
父组件: