Vue3之组件通信

通常在项目中,页面都是由很多个组件组成的,那么组件之间的通信(传值)我们该如何处理呢,我们通常采用如下方案处理:

父传子-Props

小细节:虽然理论上你也可以在向子组件传递 props 时使用驼峰形式(使用dom模板时例外),但实际上为了和 HTML attribute 对齐,我们通常会将其写为 kebab-case 形式

// 父组件
<template>
  <MyComponent greeting-message="hello" />
</template>
// MyComponent.vue
<template>
  <span>{{ greetingMessage }}</span>
</template>
<script setup lang=“ts”>
  defineProps({
    greetingMessage: String,
    hello?: String // 这是配合ts的写法
    // 配合校验+默认值
    world: {
      type: String,
      required: true,
      default: '100'
    },
  })
</script>

要记住,Props是单向数据流,切不可以直接改变它,如果我们需要对Props的值进行修改,可以尝试以下操作:

  • 通过ref
const props = defineProps(['initialCounter'])

// 计数器只是将 props.initialCounter 作为初始值
// 像下面这样做就使 prop 和后续更新无关了
const counter = ref(props.initialCounter)
  • 通过computed
const props = defineProps(['size'])
// 该 prop 变更时计算属性也会自动更新
const normalizedSize = computed(() => props.size.trim().toLowerCase())

子传父-emit

// 子组件MyButton.vue
<template>
  <button @click="$emit('increaseBy', 1)">
    Increase by 1
  </button>
</template>
<script setup>
// 我们在setup中其实是没法直接使用$emit,需要引入defineEmits
import { defineEmits } from "vue";
// 这里定义emit事件的名称,比如上面click需要emit的方法,如下写法是等同于$emit('increaseBy', 1)
let emit = defineEmits(["increaseBy"]);
emit("increaseBy", 1)
<script>

// 父组件
<template>
  <MyButton @increase-by="increaseCount" />
</template>
<script setup>
  import { ref } from "vue";
  let count = ref(0)
  function increaseCount(n) {
    count.value += n
  }
</script>

嵌套组件-provide&inject

<!-- 在供给方组件内 -->
<script setup>
import { provide, ref } from 'vue'
const location = ref('hello')
function updateLocation() {
  location.value = 'word'
}
provide('location', {
  location,
  updateLocation
})
</script>

<!-- 在注入方组件 -->
<script setup>
import { inject } from 'vue'
// 这里接收的就是provide提供的值
const { location, updateLocation } = inject('location')
</script>

<template>
  <button @click="updateLocation">{{ location }}</button>
</template>

兄弟组件-mitt

在vue2中我们可以通过new一个Vue的实例来充当bus总线,vue3中变成了mitt,不过我们需要npm install mitt ---save。

// utils.js
import mitt from "mitt";
const bus = mitt();
export default bus
<!-- 在发布方 -->
<script setup>
// 这个路径不是固定写法,根据你项目决定
import bus from "@/utils"
bus.emit("emitFun", "你可能需要传递的数据")
</script>

<!-- 在接收方 -->
<script setup>
// 这个路径不是固定写法,根据你项目决定
import bus from "@/utils"
import { onMounted } from "vue";
onMounted(()=>{
  // 第一个参数就是emit传递的第一个参数,是对应的
  bus.on("emitFun", (params) => {
    console.log(params); // "你可能需要传递的数据"
  })
})
</script>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 父传子 1、在父组件的子组件标签自定义一个属性,挂载要传输的变量 2、在子组件中通过props来接受数据,...
    文菇凉666阅读 265评论 0 1
  • 本文整理来自深入Vue3+TypeScript技术栈-coderwhy大神新课[https://ke.qq.com...
    Imkata阅读 7,353评论 0 0
  • 前言 您将在本文当中了解到,往网页中添加数据,从传统的dom操作过渡到数据层操作,实现同一个目标,两种不同的方式....
    itclanCoder阅读 25,900评论 1 12
  • 一、组件通信(props) 1、说明 通过上一小节的学习我们已经知道了在Vue中怎么创建组件和使用组件,而组件与组...
    杨健kimyeung阅读 198评论 0 0
  • 一、组件通信(props) 1、说明 通过上一小节的学习我们已经知道了在Vue中怎么创建组件和使用组件,而组件与组...
    唯老阅读 509评论 0 2