一、 setup
·1、Props 和 Context
setup 接受两个参数 props 和 context。
简例:
// MyBook.vue
import { toRefs, toRef } from 'vue'
setup(props) {
const { title } = toRefs(props)
console.log(title.value)
}
export default {
setup(props, context) {
const { title } = toRefs(props)
console.log(title.value)
// 如果 props 传入的参数是可选,则用 toRef
const name = toRef(props, 'name')
console.log(name.value)
// Attribute (非响应式对象,等同于 $attrs)
console.log(context.attrs)
// 插槽 (非响应式对象,等同于 $slots)
console.log(context.slots)
// 触发事件 (方法,等同于 $emit)
console.log(context.emit)
// 暴露公共 property (函数)
console.log(context.expose)
}
}
执行 setup 时,你只能访问以下 property
- props
- attrs
- slots
- emit
2、结合模板使用
简例
<!-- MyBook.vue -->
<template>
<div>{{ collectionName }}: {{ readersNumber }} {{ book.title }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
props: {
collectionName: String
},
setup(props) {
const readersNumber = ref(0)
const book = reactive({ title: 'Vue 3 Guide' })
// 暴露给 template
return {
readersNumber,
book
}
}
}
</script>
// 也可以返回渲染函数
import { h, ref } from 'vue'
export default {
setup(props, { expose }) {
const count = ref(0)
const increment = () => ++count.value
expose({ // 通过 expose 去避免返回渲染函数导致其他变量无法运用在模板上
increment
})
return () => h('div', count.value)
}
}
尽量避免使用 this ,因为 setup 是创建组件之前调用的,很可能因为作用域不同,导致使用 this 会混淆。
二、生命周期钩子
选项式 API | Hook inside setup |
---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
想要在beforeCreate 和 created 的钩子运行的代码可以直接在 setup 里面写,其他的如下简例:
// MyBook.vue
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
三、Provide / Inject
provide 允许通过两个参数定义,provide(name, value)
简例
<!-- src/components/MyMap.vue -->
<template>
<MyMarker />
</template>
<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'
export default {
components: {
MyMarker
},
setup() {
provide('location', 'North Pole')
provide('geolocation', {
longitude: 90,
latitude: 135
})
}
}
</script>
然后我们需要用 inject 来接收,同样的也是两个参数 inject(name, 默认值)
简例
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
setup() {
const userLocation = inject('location', 'The Universe')
const userGeolocation = inject('geolocation')
return {
userLocation,
userGeolocation
}
}
}
</script>
在使用 provide 和 inject 的时候,有以下几点需要注意的
- 如果传的值需要更改的时候,更改的位置要在 provide 的组件里面
- 如果有需要到在 inject 的组件里更改,provide 可以传递更改的方法
- 为了避免误操作更改 provide 传递的值,可以设置 readonly
简例
<!-- 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>