您的位置:

Vue3 组件通信:从基础到高级

一、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。在实际开发中,应根据场景选择合适的通信方式来进行组件间的数据传递,以实现更高效的应用。