组合API-provide和inject(依赖注入)
目标:掌握使用provide函数和inject函数完成后代组件数据通讯
provide和inject在Vue 2中已经被广泛应用,不是新鲜API,3.0重新认识一下它们两个。
一句话介绍:provide可以向所有子孙组件提供数据以及提供修改数据的方法,子孙组件用inject使用数据。
父级组件使用provide向下进行传递数据;
子级组件使用inject来获取上级组件传递过来的数据;
使用场景:有一个父组件,里头有子组件,有孙组件,有很多后代组件,共享父组件数据。
演示代码:
<template>
<div>
<div>父子组件的交互</div>
<button @click='money=200'>修改</button>
<hr>
<Child :money='money' @send-money='getMoney' />
</div>
</template>
<script>
import Child from './Child.vue'
import { ref, provide } from 'vue'
export default {
name: 'App',
components: { Child },
setup () {
// 直接把数据传递出去
provide('moneyInfo', 1000)
const money = ref(100)
const getMoney = (value) => {
// value就是子组件传递回来的钱
money.value = money.value - value
}
return { money, getMoney }
}
}
</script>
孙子组件
<template>
<div>
孙子组件:{{moneyInfo}}
</div>
</template>
<script>
import { inject } from 'vue'
export default {
name: 'GrandSon',
setup () {
const moneyInfo = inject('moneyInfo')
return { moneyInfo }
}
}
</script>
子组件
<template>
<div>
子组件 {{money}} --- {{moneyInfo}}
</div>
<button @click='getMoney'>点击</button>
<GrandSon />
</template>
<script>
import GrandSon from '@/GrandSon'
import { inject } from 'vue'
export default {
name: 'Child',
components: { GrandSon },
// 子组件触发的自定义事件需要在emits选项中进行声明(直观的看到本组件触发了那些自定义事件)
emits: ['send-money'],
props: {
money: {
type: Number,
default: 0
}
},
setup (props, context) {
const moneyInfo = inject('moneyInfo')
// Vue3中,使用形参props获取所有父组件传递的数据
// props的数据是只读的,不可以在子组件直接修改
const getMoney = () => {
console.log(props.money)
// this.$emit('send-money', 50)
// 向父组件传递数据50
context.emit('send-money', 50)
}
return { getMoney, moneyInfo }
}
}
</script>
总结:
- 父传子孙数据:provide
- 子孙得到数据:inject
孙子组件把数据直接传递给爷爷
<template>
<div>
<div>父子组件的交互</div>
<button @click='money=200'>修改</button>
<hr>
<Child :money='money' @send-money='getMoney' />
</div>
</template>
<script>
import Child from './Child.vue'
import { ref, provide } from 'vue'
export default {
name: 'App',
components: { Child },
setup () {
// 直接把数据传递出去
provide('moneyInfo', 1000)
// 把一个函数传递给孙子
const handleMoney = (value) => {
console.log('孙子传递的数据:', value)
}
provide('handleMoney', handleMoney)
const money = ref(100)
const getMoney = (value) => {
// value就是子组件传递回来的钱
money.value = money.value - value
}
return { money, getMoney }
}
}
</script>
孙子组件
<template>
<div>
孙子组件:{{moneyInfo}}
</div>
<button @click='handleSend'>点击给爷爷数据</button>
</template>
<script>
import { inject } from 'vue'
export default {
name: 'GrandSon',
setup () {
const moneyInfo = inject('moneyInfo')
const handleMoney = inject('handleMoney')
const handleSend = () => {
// 调用爷爷传递函数
handleMoney(200)
}
return { moneyInfo, handleSend }
}
}
</script>
总结:子组件传递数据给爷爷组件,需要通过provide一个函数的方式实现
- 爷爷组件传递一个函数,后续通过函数的形参获取数据
- 孙子组获取并调用该函数传递数据