setup
是一个组件选项,在组件被创建之前,props
被解析之后执行。它是组合式 API 的入口。
他接受两个参数:
{Data} props
{SetupContext} context
通常情况下,我们用props
把数据传递给子组件,子组件通过emit
把数据传递给父组件。但是当层级比较多的时候,比如祖先组件和重孙组件需要传递数据,而中间的那些组件不需要,用props
和emit
就显得有些繁琐了,这时候我们可以用provide
和inject
。provide
提供一个具有名字的变量传递给子孙组件,子孙组件用inject
接收同名变量,就能够使用了。
区别于选项模式,在setup
中,我们要手动引入provide
和inject
,话不多说,直接上示例。
父组件index.vue
:
<script lang="ts">
import { ref,provide } from "vue"
import InjectTest from './injectTest.vue'
export default {
components:{InjectTest},
setup(){
//创建hello变量
const hello = ref<string>("hello world")
//传递给子组件的变量message,值是hello变量
//这里也可以直接传递一个值,比如provide("message","hello wrold")
provide("message",hello)
//一个用来修改hello变量的函数
const changeProvide = (val:string)=>{
hello.value = val
}
//把修改hello变量的函数,传递给子组件
provide("changeProvide",changeProvide)
//在父组件中修改hello变量,2秒后可以看到页面上子组件的数据也发生了变化。
setTimeout(()=>{
hello.value = "你好,世界"
},2000)
return {
}
},
}
</script>
<template>
<div>
<InjectTest></InjectTest>
</div>
</template>
子组件injectTest.vue
:
<script lang="ts">
import { inject } from 'vue'
export default {
setup(){
//接收父组件变量message
const injectMessage = inject("message")
//接收父组件修改message的函数changeProvide,可以在子组件修改父组件provide变量
const changeProvide = inject("changeProvide")
//其实对于响应式变量和对象来说,子组件也可以直接修改父组件的变量,
//但是建议不要这样修改,如果这个provide有很多子组件在用,
//那么通过子组件修改变量的值,会让维护变得异常麻烦。
const changeMessage = ()=>{
injectMessage.value = '66666666666'
}
return {
injectMessage,
changeProvide,
changeMessage
}
}
}
</script>
<template>
<div>{{injectMessage}}</div>
<button @click="changeProvide('子孙组件修改数据')">inject</button>
<button @click="changeMessage">按钮</button>
</template>
通过子组件的注释,咱们了解到,尽量不要用子组件直接修改provide
的值,如果从父组件出发就想禁止子组件修改的话,咱们可以引入readonly
,修改父组件index.vue
的两行代码:
import { ref,provide,readonly } from "vue"
provide("message",readonly(hello))
这个时候,provide
的值对于子组件来说,就是只读的,子组件不能直接修改provide
变量,但是可以通过父组件传递给子组件的方法去修改,例如上边的子组件,changeProvide
方法可以修改,但是changeMessage
方法不能修改。
下边是setup
语法糖的inject
代码,provide
同理,因为都是引入的provide
和inject
,语法糖和setup
选项没有什么不同,除了不用return
函数或者变量。
语法糖子组件injectTest.vue
:
<script setup lang="ts">
import { inject } from 'vue'
const injectMessage = inject("message")
const changeProvide = inject("changeProvide")
const changeMessage = ()=>{
//injectMessage.value如果红线报错的话,可以这样写
(injectMessage as any).value = '66666666666'
}
</script>
<template>
<div>{{injectMessage}}</div>
<button @click="changeProvide('子孙组件修改数据')">inject</button>
<button @click="changeMessage">按钮</button>
</template>
有帮助的话,点个赞呗!关于vue3的一切疑问,大家可以在评论区留言提问。