组件间传值常见的3种情况
- 父传子
- 子传父
- 跨组件
父传子
vue3 中父传子和 vue2 中类似,不同点是子组件接收数据时 props 的定义方式不同,下面是具体步骤。
步骤
- 父组件提供数据
- 父组件将数据通过属性传递给子组件
- 子组件通过定义 defineProps 定义属性进行接收
- 子组件内部使用,<template />中和<script />中
代码
父组件
<script setup>
// 引入 watch
import { ref } from "vue";
import Child from "./components/Child.vue";
// 父组件定义数据
const money = ref(1000)
</script><template>
<div>
<h1>父组件的money: {{money}}</h1>
<hr />
<!-- 通过属性传递给子组件 -->
<Child :money="100" />
</div>
</template>
子组件
<script setup>
// 组件接收数据
const props = defineProps({
money: {
type: Number,
default: 10
}
})// JS 中使用
console.log('子组件接收到的数据', props.money)</script>
<template>
<div>
<!-- 模版中使用 -->
<p>我是一个子组件,我从父组件接收到的数据为:{{money}}</p>
</div>
</template>
总结
定义和使用几乎和 vue2 相同,vue3 中只是使用了 defineProps 这个函数来定义组件要接受的数据。
子传父
vue3 中子传父和 vue2 中类似,不同点是子组件定义 emit 事件的方式不同,下面是具体步骤。
步骤
- 子组件通过 defineEmits 定义 emit 事件
- 子组件通过自己触发自定义的 emit 事件传递数据
- 父组件绑定子组件定义的 emit 事件
- 父组件在绑定的子组件的 emit 事件函数中接收数据
代码
父组件
<script setup>
// 引入 watch
import { ref } from "vue";
import Child from "./components/Child.vue";const money = ref(1000)
// 父组件绑定子组件定义的 emit 事件
const giveMoney = (money) => {
console.log('子组件要的钱:', money)
}
</script><template>
<div>
<h1>父组件的money: {{money}}</h1>
<hr />
<!-- 通过属性传递给子组件 -->
<!-- 父组件绑定子组件定义的 emit 事件 -->
<Child :money="100" @giveMoney="giveMoney" />
</div>
</template>
子组件
<script setup>
// 组件接收数据
const props = defineProps({
money: {
type: Number,
default: 10
}
})
// JS 中使用
console.log('子组件接收到的数据', props.money)
// 子组件通过 defineEmits 定义 emit 事件
const emits = defineEmits(['giveMoney'])
// 子组件通过自己触发自定义的 emit 事件传递数据
const giveMoney = () => {
emits('giveMoney', 100)
}</script>
<template>
<div>
<!-- 模版中使用 -->
<p>我是一个子组件,我从父组件接收到的数据为:{{money}}</p>
<button @click="giveMoney">给钱</button>
</div>
</template>
总结
定义和使用几乎和 vue2 相同,vue3 中只是使用了 defineEmits 这个函数。
跨组件传值
通常的情况下,如果想实现跨组件传值,可以在组件间通过 props 一层一层传递。如下图:
但是这种传值方式效率低,中间组件要做和自己无关的业务操作。vue3 中也提供了跨组件传值的方式。
如图所示,通过 provide 和 inject 函数可以简便的实现跨级组件通讯。使用方式也比较简单明了
步骤
- 在组件中通过 provide 定义要跨组件传递的值。一旦在组件中使用 provide 定义要传递的值,那么这个组件的所有子组件都可以获取到这个值。
- 在定义 provide 的任意层级下的子组件通过 inject 获取传递的值。
代码
<script setup>
// 引入 provide
import { provide } from "vue";
import App1 from './components/App1.vue'// provide 提供要跨组件传递的值。所有 App 的子组件都可以获取这个值
provide('theme', 'red')</script>
<template>
<div style="border: 1px solid red; margin: 16px;">
<h1>App组件</h1>
<App1></App1>
</div>
</template>
组件
<script setup>
import App2 from './App2.vue'
</script><template>
<div style="border: 1px solid red; margin: 16px;">
<h2>App1组件</h2>
<App2></App2>
</div>
</template>
<script setup>
import App3 from './App3.vue'
</script><template>
<div style="border: 1px solid red; margin: 16px;">
<h3>App2组件</h3>
<App3></App3>
</div>
</template>
<script setup>
import { inject } from 'vue'
// 通过 inject 获取值
const theme = inject('theme')
</script><template>
<div style="border: 1px solid red; margin: 16px;">
<h4>App3组件</h4>
<p>{{theme}}</p>
</div>
</template>
总结
- provide 和 inject 是解决跨级组件通讯的方案
-
- provide 提供后代组件需要依赖的数据或函数
- inject 注入 provide 提供的数据或函数