vue3之Composition API详解
Composition API
也叫组合式API,是Vue3.x的新特性。
通过创建 Vue 组件,我们可以将接口的可重复部分及其功能提取到可重用的代码段中。仅此一项就可以使我们的应用程序在可维护性和灵活性方面走得更远。然而,我们的经验已经证明,光靠这一点可能是不够的,尤其是当你的应用程序变得非常大的时候——想想几百个组件。在处理如此大的应用程序时,共享和重用代码变得尤为重要通俗的讲:
没有
Composition API
之前vue相关业务的代码需要配置到option的特定的区域,中小型项目是没有问题的,但是在大型项目中会导致后期的维护性比较复杂,同时代码可复用性不高。Vue3.x中的composition-api就是为了解决这个问题而生的compositon api提供了以下几个函数:
setup
ref
reactive
watchEffect
watch
computed
toRefs
- 生命周期的
hooks
新的提示:setup
组件选项在 创建组件之前执行,一旦props
被解析,并充当合成API
的入口点
由于在执行使用setup
时尚未创建组件实例,因此在setup
选项中没有this
。这意味着,除了props
之外,你将无法访问组件中声明的任何属性——本地状态、计算属性或方法。
setup
函数时,它将接受两个参数:props
context
1. Props
setup
函数中的第一个参数是props
。正如在一个标准组件中所期望的那样,setup
函数中的props
是响应式的,当传入新的prop
时,它将被更新
// MyBook.vueexport default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
注意:
但是,因为如果需要解构 prop,可以通过使用props
是响应式的,你不能使用ES6
解构,因为它会消除prop
的响应性。
setup
函数中的 toRefs
来安全地完成此操作。// MyBook.vueimport { toRefs } from 'vue'setup(props) {
const { title } = toRefs(props)console.log(title.value)
}
2. 上下文
传递给setup
函数的第二个参数是context
。context
是一个普通的 JavaScript 对象,它暴露三个组件的 property
// MyBook.vueexport default {
setup(props, context) {
// Attribute (非响应式对象)
console.log(context.attrs)// 插槽 (非响应式对象)
console.log(context.slots)// 触发事件 (方法)
console.log(context.emit)
}
}
context
是一个普通的 JavaScript 对象,也就是说,它不是响应式的,这意味着你可以安全地对context
使用 ES6 解构
// MyBook.vue
export default {
setup(props, { attrs, slots, emit }) {
...
}
}
3. setup组件的 propertyattrs
和slots
是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以attrs.x
或slots.x
的方式引用 property。请注意,与props
不同,attrs
和slots
是 非响应式的。如果你打算根据attrs
或slots
更改应用副作用,那么应该在onUpdated
生命周期钩子中执行此操作。
执行
setup
时,组件实例尚未被创建。因此,你只能访问以下 property:
props
attrs
slots
emit
data
computed
methods
在看
setup
结合模板使用之前,我们首先得知道ref
和 reactive
方法。如果
setup
返回一个对象则可以在模板中绑定对象中的属性和方法,但是要定义响应式数据的时候可以使用ref
, reactive
方法定义响应式的数据错误写法:
{{msg}}
.home {
position: relative;
}
正确写法一:
ref用来定义响应式的 字符串、 数值、 数组、
Bool
类型
import {
ref
} from 'vue'
{{msg}}
-
{{item}}
.home {
position: relative;
}
正确写法二: reactive 用来定义响应式的对象
import {
reactive
} from 'vue'
{{msg}}
-
{{item}}
{{setupData.title}}
.home {
position: relative;
}
说明:要改变ref定义的属性名称需要通过
属性名称.value
来修改,要改变reactive
中定义的对象名称可以直接5. 使用
this
在二、toRefs - 解构响应式对象数据setup()
内部,this
不会是该活跃实例的引用,因为setup()
是在解析其它组件选项之前被调用的,所以setup()
内部的this
的行为与其它选项中的this
完全不同。这在和其它选项式 API 一起使用setup()
时可能会导致混淆
把一个响应式对象转换成普通对象,该普通对象的每个property
都是一个ref
,和响应式对象property
一一对应
解构响应式对象数据Username: {{username}}
Age: {{age}}
当想要从一个组合逻辑函数中返回响应式对象时,用 toRefs 是很有效的,该 API 让消费组件可以 解构 / 扩展(使用
…
操作符)返回的对象,并不会丢失响应性:
function useFeatureX() {
const state = reactive({
foo: 1,
bar: 2,
})// 对 state 的逻辑操作
// ....// 返回时将属性都转为 ref
return toRefs(state)
}export default {
setup() {
// 可以解构,不会丢失响应性
const { foo, bar } = useFeatureX()return {
foo,
bar,
}
},
}
三、computed - 计算属性
解构响应式对象数据+computed
{{fullName}}
四、readonly “深层”的只读代理
传入一个对象(响应式或普通)或 ref,返回一个原始对象的只读代理。一个只读的代理是“深层的”,对象内部任何嵌套的属性也都是只读的
readonly - “深层”的只读代理original.count: {{original.count}}
copy.count: {{copy.count}}
五、watchEffect
在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它。
watchEffect - 侦听器{{data.count}}
六、watch 、watch 与watchEffect区别 对比
watchEffect
,watch
允许我们:- 懒执行,也就是说仅在侦听的源变更时才执行回调;
- 更明确哪些状态的改变会触发侦听器重新运行;
- 访问侦听状态变化前后的值
watch - 侦听器count1: {{data.count1}}
count2: {{data.count2}}
访问侦听状态变化前后的值
watch - 侦听器
懒执行,也就是说仅在侦听的源变更时才执行回调
watch - 侦听器num1={{num1}}
num2={{num2}}
七、组合式api生命周期钩子 你可以通过在生命周期钩子前面加上 “on” 来访问组件的生命周期钩子。
下表包含如何在 setup () 内部调用生命周期钩子:
选项式 API | Hook inside setup |
---|---|
beforeCreate |
不需要* |
created |
不需要* |
beforeMount |
onBeforeMount |
mounted |
onMounted |
beforeUpdate |
onBeforeUpdate |
updated |
onUpdated |
beforeUnmount |
onBeforeUnmount |
unmounted |
onUnmounted |
errorCaptured |
onErrorCaptured |
renderTracked |
onRenderTracked |
renderTriggered |
onRenderTriggered |
因为setup
是围绕beforeCreate
和created
生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在setup
函数中编写
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
八、Provider Inject 通常,当我们需要将数据从父组件传递到子组件时,我们使用 props。想象一下这样的结构:你有一些深嵌套的组件,而你只需要来自深嵌套子组件中父组件的某些内容。在这种情况下,你仍然需要将 prop 传递到整个组件链中,这可能会很烦人
对于这种情况,我们可以使用1. 非组合式api中的写法provide
和inject
对父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个provide
选项来提供数据,子组件有一个inject
选项来开始使用这个数据
2. 组合式api中的写法
Provider:
在setup()
中使用provide
时,我们首先从vue
显式导入provide
方法。这使我们能够调用provide
时来定义每个property
provide
函数允许你通过两个参数定义 property
:property
的name
(类型)
property
的value
MyMap
组件,我们提供的值可以按如下方式重构:
Inject:
在setup()
中使用inject
时,还需要从vue
显式导入它。一旦我们这样做了,我们就可以调用它来定义如何将它暴露给我们的组件。
inject
函数有两个参数:- 要注入的
property
的名称 - 一个默认的值 (可选)
MyMarker
组件,可以使用以下代码对其进行重构:
Provider Inject 响应性
父组件:
import {
provide,
ref,
reactive
} from 'vue'setup() {
const location = ref('北京')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'https://www.it610.com/article/上海'
}
provide('location', location);
provide('geolocation', geolocation);
return {
updateLocation
}
}
子组件:
import { inject } from 'vue'export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')return {
userLocation,
userGeolocation
}
}
}
【vue3之Composition API详解】
文章图片
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 期刊|期刊 | 国内核心期刊之(北大核心)
- 生活随笔|好天气下的意外之喜
- 感恩之旅第75天
- python学习之|python学习之 实现QQ自动发送消息