组合式API
- 如果能够将同一个
逻辑关注点
相关代码收集在一起会更好,而这正是组合式API使我们能够做到的; - 新的
setup
选项在组件被创建之前执行,一旦props
被解析完成,它就将被作为组合式API的入口; setup
的调用发生在data
property、computed
property或methods
被解析之前,所以它们无法在setup
中被获取;- 在js中,
Number
或String
等基本类型是通过值而非引用传递的; ref
为我们的值创建了一个响应式引用;computed
输出的是一个只读的响应式引用;- 使用
toRefs
创建对props中的user
property的响应式引用; - 继续其他任务之前,我们首先要将上述代码提取到一个独立的
组合式函数
中; - 现在我们有了多个单独的功能模块,接下来就可以开始在组件中引入并使用它们了。
Setup
- 使用
setup
函数时,它将接收两个参数:props
和context
; props
是响应式的,不能使用ES6解构,它会消除prop的响应性;- 如果需要解构prop,可以在
setup
函数中使用toRefs
函数来完成此操作; - 传递给
setup
函数的第二个参数是context
。context
是一个普通的js对象,暴露了其它可能在setup
中有用的值;
export default {
setup(props, context) {
console.log(context.attrs)
console.log(context.slots)
console.log(context.emit)
console.log(context.expose)
}
}
context
是一个普通的js对象(非响应式),意味着你可以安全地对context
使用ES6解构:
export default {
setup(props, { attrs, slots, emit, expose }) {
...
}
}
attrs
和slots
是有状态的对象,但其property是非响应式的;- 如果打算根据
attrs
或slots
的更改应用副作用,那么应该在onBeforeUpdate
生命周期钩子中执行此操作; - 执行
setup
时,你只能访问以下property:props
、arrts
、slots
、emit
,你将无法访问data
、computed
、methods
、refs
; - 注意,从
setup
返回的refs
在模板中访问时是被自动浅解包
的,因此不应在模板中使用.value
; - 可以通过调用
expose
来解决这个问题,给它传递一个对象,其中定义的property将可以被外部组件实例访问,譬如通过父组件的模板ref
访问。
生命周期钩子
- 你可以通过在生命周期钩子前面加上“on”来访问组件的生命周期钩子;
- 因为
setup
是围绕beforeCreate
和created
生命周期钩子运行的,所以不需要显式地定义它们; - 这些函数接受一个回调函数,当钩子被组件调用时会被执行。
Provide/Inject
- 当使用响应式provide/inject值时,建议尽可能将响应式property的所有修改限制在定义provide的组件内部;
- 有时我们需要在注入数据的组件内部更新 inject 的数据;
- 在这种情况下,我们建议 provide 一个方法来负责改变响应式 property;
- 如果要确保通过 provide 传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用
readonly
; - 使用provide:
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'South Pole'
}
provide('location', readonly(location))
provide('geolocation', readonly(geolocation))
provide('updateLocation', updateLocation)
}
}
</script>
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
const updateUserLocation = inject('updateLocation')
return {
userLocation,
userGeolocation,
updateUserLocation
}
}
}
</script>
模板引用