这里是完整的目录图片,由于整篇文章篇幅太长,拆分成了几篇来展示
4. context 之 slots 和 attrs
setup() 中的 context参数
我们都知道在 Vue3 语法当中 setup() 的第一个参数是 props,第二个参数是 context
props 用 defineProps API 来替换掉了
而 context 是一个对象,并且这个对象中有三个属性,分别是 attrs, slots, emit
当我们需要事件派发的时候,直接使用 emit 就可以了
那么 setupContext.attrs 以及 setupContext.slots 在 script setup 语法当中应该怎样使用呢?
在
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
useSlots 和 useAttrs 是真实的运行时函数,它的返回与 setupContext.slots 和 setupContext.attrs 等价。
它们同样也能在普通的组合式 API 中使用。
已经弃用的 useContext()
在查找相关资料的时候有看到关于 useContext() 的用法 (可以通过 useContext() 从上下文中获取 emit slots 和 attrs),但是现在关于 useContext 已经弃用了,废除了这个语法,被拆分成上面的 useAttrs 和 useSlots
以下图片来自别的参考资料,但是现在已经弃用了
测试使用报错 : The requested module '/node_modules/.vite/deps/vue.js?v=8da96c73' does not provide an export named 'useContext' (at child.vue:6:33)
<!-- 已弃用 -->
<script setup>
import { useContext } from "vue";
const { slots, attrs } = useContext();
</script>
5. defineExpose()
Vue 3 可以利用 expose 结合 ref 来让父组件使用子组件的数据 ( 可以对数据进行修改 )和方法
在 Vue 3 的新特性中,如果使用的是 options api 类型的组件,在不声明 expose 的时候,默认暴露当前组件实例的全部内容 (所有的属性和方法),如果使用 expose 选项的话,只有 expose 中的内容才会暴露 (expose:[ ] 就表示什么都不暴露,可以利用这个特性来提高组件的使用规范 )
如果使用的是 setup script 的语法糖, 默认是关闭 expose 的, 子组件未暴露的数据以及方法在父组件中无法直接获取引用,需要子组件使用 defineExpose 将其主动暴漏出来
Vue 3 setup() 语法
父组件
<template>
<div>
<h2 @click="clickEvent">我是父组件!</h2>
<Child ref="son" />
</div>
</template>
<script>
import {defineComponent} from 'vue'
import Child from './child.vue'
export default defineComponent({
components:{
Child
},
setup(){
function clickEvent (){
console.log("click here !")
// 访问子组件中的属性
console.log(this.$refs.son.msg)
// 调用子组件中的方法
this.$refs.son.m1()
}
return {
clickEvent
}
}
})
</script>
子组件
<!-- 子组件 -->
<template>
<span>我是子组件! -- msg: {{ msg }}</span>
</template>
<script>
import {defineComponent,ref} from 'vue'
export default defineComponent({
setup(){
const msg = ref('this is a msg from child component')
const m1 = ()=>{
console.log("this is method m1 at child component")
}
return{
msg,
m1
}
}
})
</script>
<script setup>
语法糖的写法
父组件
<template>
<div>
<h2 @click="clickEvent">我是父组件!</h2>
<Child ref="son" />
</div>
</template>
<script setup>
import {ref} from 'vue'
import Child from './child.vue'
const son = ref(null)
function clickEvent (){
console.log("click here !")
// 访问子组件中的属性
console.log(son.value.msg)
// 调用子组件中的方法
son.value.m1()
}
</script>
子组件
<template>
<span>我是子组件! -- msg: {{ msg }}</span>
</template>
<script setup>
import {ref} from 'vue'
const msg = ref('this is a msg from child component')
const m1 = ()=>{
console.log("this is method m1 at child component")
}
defineExpose({
msg,
m1
})
</script>
就像这个例子子组件中暴露的这样,将属性 msg , 方法 m1 暴露出来,父组件通过 ref 获取到子组件的实例就可以访问到了
小结
- defineExpose 可以直接使用,无需引入
- 当父组件通过模板引用的方式获取到当前组件的实例,获取到的实例会像是这个样子的 {a:number,b:number} (ref 会和在普通实例中一样被自动解包)
vue3 script setup 语法糖用了才知道有多爽 (一)
vue3 script setup 语法糖用了才知道有多爽 (二)