setup(props, context) {
...
}
一、参数
使用setup函数时,它将接受两个参数:
- props
- context
让我们更深入地研究如何使用每个参数
二、Props
setup函数中的第一个参数是props。正如在一个标准组件中所期望的那样,setup函数中的props是响应式的,当传入新的prop时,它将被更新。
export default {
props: {
title: String
},
setup(props, context) {
console.log(props.title)
...
}
}
Warning
:因为props
是响应式的,你不能使用ES6解构,因为它会消除prop的响应式。
如果需要解构prop,可以通过使用setup函数中的toRefs来安全地完成此操作
import { toRefs } from 'vue
export default {
props: {
title: String
},
setup(props, context) {
const { title } = toRefs(props)
console.log(title.value)
...
}
}
三、context
context参数是一个普通的javascript对象,它对组件暴露三个属性:attrs、slots、emit。
export default {
setup(props, context) {
// Attribute(非响应式对象)
console.log(context.attrs)
// 插槽(非响应式对象)
console.log(context.slots)
// 触发事件(方法)
console.log(context.emit)
}
}
context是一个普通的JavaScript对象,也就是说,它不是响应式的,这意味着你可以安全地对context使用ES6解构。
export default {
setup(props, { attrs, slots, emmit }) {
...
}
}
attrs和slots是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以attrs.x或slots.x的方式引用property。
请注意,与props不同,attrs和slots是非响应式的。如果你打算根据attrs或slots更改应用副作用,那么应该在onUpdated
生命周期钩子中执行此操作。
访问组件的property
执行setup时,组件实例尚未被创建。因此,你只能访问以下property:
- props
- attrs
- slots
- emit
换句话说,你将无法访问以下组件选项:
- data
- computed
- methods
在setup()内部,this不会是该活跃实例的引用,因为setup()是在解析其他组件选项之前被调用的,所以setup()内部的this的行为与其他选项中的this完全不同。这在和其他选项式 API一起使用setup()时可能会导致混淆。
1、attrs
用途:当父组件传递数据给子组件时,子组件不通过props接收,那么父组件传递的数据就到了setup中的context的attrs属性。
<div id="app">
<!-- 父组件传递数据给子组件 -->
<son webName="自如初"></son>
</div>
<script>
const app = Vue.createApp({
});
// 子组件不使用props接收
app.component('son', {
template:`<div>son</div>`,
setup(props, context) {
const { attrs, slots, emit} = context;
// 打印父组件传递的数据
console.log(attrs.webname);
return {};
}
});
const vm = app.mount('#app');
</script>
2、slots
用于接收渲染父组件传递的插槽内容
<div id="app">
<son>
父组件通插槽传递的内容
</son>
</div>
<script>
const app = Vue.createApp({
});
app.component('son', {
template:`<div>son</div>`,
setup(props, context) {
const { h } = Vue;
const { attrs, slots, emit} = context;
// 显示父组件传递的内容
return () => h('p', {}, slots.default());
}
});
const vm = app.mount('#app');
</script>
3、emit
向父组件触发事件。
<div id="app">
<!-- 4、父组件监听子组件发射的事件 -->
<son @sclick="getData"></son>
</div>
<script>
const app = Vue.createApp({
methods: {
// 5、实现事件
getData () {
alert(1)
}
}
});
app.component('son', {
// 1、子组件中绑定事件
template:`<div @click="sonClick">son</div>`,
setup(props, context) {
const { attrs, slots, emit} = context;
function sonClick() {
// 2、通过 emit 向父组件发射事件
emit('sclick');
}
// 3、对外暴露该事件
return { sonClick };
}
});
const vm = app.mount('#app');
</script>
4、使用渲染函数
setup还可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态: