和Vue3和解的Day14--父子组件通信

1,336 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 14 天,点击查看活动详情

说点题外话

上几篇说了父子组件通信:包括props传参和非props传参:

和Vue3和解的Day11--父子组件通信

和Vue3和解的Day12--父子组件通信

也说了选项式中子组件向父组件传参,传参的类型等等:

和Vue3和解的Day13--父子组件通信

这一篇说说在组合式setup函数和setup语法糖下父子组件中的子组件给父组件传参

说正文

image.png

子组件向父组件传参在setup函数中的写法

在选项式中子组件通过 this.$emit 向父组件传递方法和参数,但是在vue3的组合式中有一个问题:vue3组合式取消绑定了 this, 那也就意味着我们无论是在在setup函数中还是setup语法糖中都无法使用 this.$emit这种方式。

那么在组合式中提供了一个新的思路,之前我们知道 setup接收的第一个参数是 props setup 接收的第二个参数就是context, context是一个对象,里面包含了emit, 我们就是利用这个参数进行子组件向父组件传参

1.1 基本使用

  • 父组件Father
<template>
  <div>
    <son :counter="counter" @addCouter="addCouter"></son>
  </div>
</template>

<script>
import { ref } from 'vue';
import Son from './Son.vue';
export default {
  components: { Son },
  setup() {
    const counter = ref(10)
    const addCouter = () => {
      counter.value++
    }

    return {
      counter,
      addCouter
    }
  }
}
</script>
  • 子组件
<template>
  <h2>{{ counter }}</h2>
  <button @click="addCouter">+1</button>
</template>

<script>
export default {

  props: ["counter"],
  emits: ['addCouter'],
  setup(props, context) {
    const addCouter = () => {
      context.emit('addCouter')
    }

    return {
      addCouter
    }
  }
}
</script>

这里要注意的一点就是在vue3的组合式中需要我们额外将需要传递的方法定义在emits数组中。上面也说过context是一个对象,我们也可以采用解构的写法来写emit传参

<script>
export default {
  props: ["counter"],
  emits: ['addCouter'],
  setup(props, { emit }) {
    const addCouter = () => {
      emit('addCouter')
    }

    return {
      addCouter
    }
  }
}
</script>

这里也有一个需要注意的点,因为我们对context采用了解构的写法,所以在方法中传递方法和参数的时候,直接emit()即可。

1.2 传递参数

这里我就省去上文重复代码了,只留下addCounter这个方法用来传递参数

  • Father.vue
    const addCouter = params => {
      counter.value++
      console.log(params);
    }
  • Son.vue
    const addCouter = () => {
      emit('addCouter', 10)
      emit('addCouter', "string")
      emit('addCouter', ["小白"])
      emit('addCouter', {name: "小白"})
    }

image.png

这里和选项式中的结果是相同的, 后面的传参并不会覆盖前面传递的参数,但是并不建议这样做

二、子组件向父组件传参:setup语法糖

  • 父组件Father.vue
<template>
  <div>
    <son :counter="counter" @addCounter="addCounter"></son>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Son from './Son.vue';

const counter = ref(10)

const addCounter = () => {
  counter.value++
}

</script>

在父组件中引用调用子组件的方法和变量和之前是没有变化的,但是子组件会有引入新的官方提供的新方法

  • 子组件Son.vue
<template>
  <h2>{{ counter }}</h2>
  <button @click="addCouterClick">+1</button>
</template>

<script setup>

// const props = defineProps(["counter"])
const props = defineProps({
  counter: Number
})

const emits = defineEmits(["addCounter"])

const addCouterClick = () => {
  emits("addCounter")
}

</script>
  • 这里新增了一个新的方法defineEmits,和defineProps差不多一个意思,用来“收纳”我们需要传递的方法。之后再调用的方法中使用我们自定义的“收纳”方法传递即可,也就是上文的emits()。(之前是需要进行引用的,但是现在官方已经取消了引用直接使用即可)

  • 补充一点上一篇漏掉的知识点:defineProps有两种方式定义,参数可以是数组也可以是对象,上面代码中注释掉的就就是。

image.png

说再见

关于父子组件通信的:父组件向子组件传参和子组件向父组件传参就说到这里,下一篇我将开始说非父子组件通信。

难忘今宵

从前有一只北极熊买了一副墨镜,他戴了墨镜之后沉思一会儿,说到:突然好想吃竹子哦。