一、props
Vue3 中的组件通信最基础的方式就是通过 props 来进行父子组件之间的数据通信。在父组件中使用 v-bind 来将数据传递给子组件,子组件通过 props 来接收传递过来的数据。
// 父组件 <template> <child-component :message="message"></child-component> </template> <script> export default { data() { return { message: 'Hello World' } } } </script> // 子组件 <template> <p>{{message}}</p> </template> <script> export default { props: { message: { type: String, required: true } } } </script>
在上面的例子中,父组件通过 v-bind 将 message 这个数据传递给了子组件,子组件通过 props 来接收了这个数据并进行渲染。在 props 中我们还可以设置传递的值的类型、是否必填等参数。
二、emit
除了从父组件到子组件的单向传递数据外,我们还需要进行反向的数据传递。可以通过自定义事件(emit)来实现子组件向父组件传递数据。
// 子组件 <template> <button v-on:click="handleClick">Click me</button> </template> <script> export default { methods: { handleClick() { this.$emit('message', 'Hello World') } } } </script> // 父组件 <template> <child-component @message="handleMessage"></child-component> </template> <script> export default { methods: { handleMessage(message) { console.log(message) } } } </script>
在上面的例子中,子组件通过 $emit 来触发自定义事件 message 并将数据传递给了父组件,父组件通过 v-on 来监听该事件并获取子组件传递过来的数据。
三、provide / inject
Vue3 中新增了一个 provide / inject API 来进行祖先组件向后代组件的数据传递。
// 祖先组件 <template> <child-component></child-component> </template> <script> export default { provide() { return { message: 'Hello World' } } } </script> // 后代组件 <template> <p>{{message}}</p> </template> <script> export default { inject: ['message'] } </script>
在上面的例子中,祖先组件通过 provide 来提供一个名为 message 的值给其所有后代组件,在后代组件中通过 inject 来接收这个值。
四、ref / $refs
在 Vue3 中,可以在父组件中通过 ref 来获取子组件的实例对象,从而可以在父组件中调用子组件的方法或获取子组件的数据。
// 父组件 <template> <child-component ref="child"></child-component> </template> <script> export default { mounted() { this.$refs.child.sayHello() } } </script> // 子组件 <script> export default { methods: { sayHello() { console.log('Hello World') } } } </script>
在上面的例子中,父组件使用 ref 来获取子组件的实例对象,从而可以在 mounted 钩子函数中调用子组件的 sayHello 方法。
五、Teleport
在 Vue3 中,Teleport 组件可以实现在任意地方渲染组件,并保持父子组件间的关系,可以用于实现一些弹窗组件等。
// 父组件 <template> <button v-on:click="openDialog">Open Dialog</button> <teleport to="body"> <dialog :visible="isDialogVisible" @close="closeDialog"></dialog> </teleport> </template> <script> import { ref } from 'vue' import Dialog from './Dialog.vue' export default { components: { Dialog }, setup() { const isDialogVisible = ref(false) function openDialog() { isDialogVisible.value = true } function closeDialog() { isDialogVisible.value = false } return { isDialogVisible, openDialog, closeDialog } } } </script> // 子组件 - Dialog <template> <div v-if="visible"> <button v-on:click="$emit('close')">Close Dialog</button> </div> </template> <script> import { defineComponent, ref } from 'vue' export default defineComponent({ props: { visible: { type: Boolean, required: true } }, }) </script>
在上面的例子中,Teleport 组件通过 to 属性来指定要渲染的位置,在这里我们指定为 body。在父组件中点击按钮,会触发 openDialog 方法从而显示 Dialog 组件,Dialog 组件中通过 $emit 来触发 close 事件从而将 Dialog 关闭。
总结
本文介绍了 Vue3 中五种常用的组件通信方式:props、emit、provide / inject、ref / $refs 和 Teleport。在实际开发中,应根据场景选择合适的通信方式来进行组件间的数据传递,以实现更高效的应用。