阅读 66

Vue3系列--3.父子通信

父子通信

  1. 父组件向子组件传递数据:自定义属性 props
  2. 子组件向父组件传递数据 : 自定义事件 $emit()

父传子

<template>
  <div>
    <div>父子组件的交互</div>
    <button @click='money=200'>修改</button>
    <hr>
    // 2.写到组件里,值就是要传的数据
    <Child :money='money' />
  </div>
</template>

<script>
import Child from './Child.vue'
import { ref } from 'vue'

export default {
  name: 'App',
  components: { Child },
  setup () {
  //1.要传的数据 money
    const money = ref(100)
    return { money }
  }
}
</script>
复制代码
<template>
  <div>
  // 4.渲染到模板
    子组件 {{money}}
  </div>
  <button @click='getMoney'>点击</button>
</template>
<script>
export default {
  name: 'Child',
  props: {
  // 3.在props里面收一下父组件传过来的数据,要和父组件:后面保持一致都叫money
    money: {
      type: Number,
      default: 0
    }
  },
  setup (props) {
    // Vue3中,使用形参props获取所有父组件传递的数据
    // props的数据是只读的,不可以在子组件直接修改
    const getMoney = () => {
      console.log(props.money)
    }
    return { getMoney }
  }
}
</script>
复制代码

总结:

  1. 子组件模板中直接可以获取props中的属性值
  2. js代码中需要通过setup函数的第一个形参props获取属性值

子传父:

代码演示:
<template>
  <div>
    <div>父子组件的交互</div>
    <button @click='money=200'>修改</button>
    <hr>
    // 3.
    <Child :money='money' @send-money='getMoney' />
  </div>
</template>

<script>
import Child from './Child.vue'
import { ref } from 'vue'

export default {
  name: 'App',
  components: { Child },
  setup () {
    const money = ref(100)
       // 4.
    const getMoney = (value) => {
      // value就是子组件传递回来的钱
      money.value = money.value - value
    }
    return { money, getMoney }
  }
}
</script>
复制代码
<template>
代码演示:
  <div>
    子组件 {{money}}
  </div>
  <button @click='getMoney'>点击</button>
</template>
<script>
export default {
  name: 'Child',
 // 2.子组件触发的自定义事件需要在emits选项中进行声明(直观的看到本组件触发了那些自定义事件)
  emits: ['send-money'],
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
  setup (props, context) {
    // Vue3中,使用形参props获取所有父组件传递的数据
    // props的数据是只读的,不可以在子组件直接修改
    const getMoney = () => {
      console.log(props.money)
      // this.$emit('send-money', 50)
      //1. 向父组件传递数据50
      context.emit('send-money', 50)
    }
    return { getMoney }
  }
}
</script>
复制代码

总结:

  1. 通过setup函数的参数二context.emit方法触发自定义事件 context.emit('send-money', 50)
  2. 子组件触发的自定义事件需要在emits选项中进行声明(直观的看到本组件触发了那些自定义事件)

依赖注入

使用场景:有一个父组件,里头有子组件,有孙组件,有很多后代组件,共享父组件数据。

代码演示:
<template>
  <div>
    <div>父子组件的交互</div>
    <button @click='money=200'>修改</button>
    <hr>
    <Child :money='money' @send-money='getMoney' />
  </div>
</template>

<script>
import Child from './Child.vue'
 import { ref, provide } from 'vue'

export default {
  name: 'App',
  components: { Child },
  setup () {
    // 直接把数据传递出去
    provide('moneyInfo', 1000)
    const money = ref(100)
    const getMoney = (value) => {
      // value就是子组件传递回来的钱
      money.value = money.value - value
    }
    return { money, getMoney }
  }
}
</script>
复制代码
<template>
  <div>
    孙子组件:{{moneyInfo}}
  </div>
</template>
<script>
 import { inject } from 'vue'

export default {
  name: 'GrandSon',
  setup () {
    const moneyInfo = inject('moneyInfo')
    return { moneyInfo }
  }
}
</script>
复制代码
<template>
  <div>
    子组件 {{money}} --- {{moneyInfo}}
  </div>
  <button @click='getMoney'>点击</button>
  <GrandSon />
</template>

<script>
import GrandSon from '@/GrandSon'
import { inject } from 'vue'
export default {
  name: 'Child',
  components: { GrandSon },
  // 子组件触发的自定义事件需要在emits选项中进行声明(直观的看到本组件触发了那些自定义事件)
  emits: ['send-money'],
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
  setup (props, context) {
     //当然父组件也可以通过注入的方式来获取爷爷组件传的数据
    const moneyInfo = inject('moneyInfo')
    // Vue3中,使用形参props获取所有父组件传递的数据
    // props的数据是只读的,不可以在子组件直接修改
    const getMoney = () => {
      console.log(props.money)
      // this.$emit('send-money', 50)
      // 向父组件传递数据50
      context.emit('send-money', 50)
    }
    return { getMoney, moneyInfo }
  }
}
</script>
复制代码

总结:

  1. 父传子孙数据:provide
  2. 子孙得到数据:inject

孙子把数据直接传递给爷爷

<template>
  <div>
    <div>父子组件的交互</div>
    <button @click='money=200'>修改</button>
    <hr>
    <Child :money='money' @send-money='getMoney' />
  </div>
</template>

<script>
import Child from './Child.vue'
import { ref, provide } from 'vue'

export default {
  name: 'App',
  components: { Child },
  setup () {
    // 直接把数据传递出去
    provide('moneyInfo', 1000)
    // 把一个函数传递给孙子
    const handleMoney = (value) => {
      console.log('孙子传递的数据:', value)
    }
    provide('handleMoney', handleMoney)
    const money = ref(100)
    const getMoney = (value) => {
      // value就是子组件传递回来的钱
      money.value = money.value - value
    }
    return { money, getMoney }
  }
}
</script>
复制代码
<template>
  <div>
    孙子组件:{{moneyInfo}}
  </div>
  <button @click='handleSend'>点击给爷爷数据</button>
</template>
<script>
import { inject } from 'vue'

export default {
  name: 'GrandSon',
  setup () {
    const moneyInfo = inject('moneyInfo')
    const handleMoney = inject('handleMoney')
    const handleSend = () => {
      // 调用爷爷传递函数
      handleMoney(200)
    }
   return { moneyInfo, handleSend }
  }
}
</script>
复制代码

总结:子组件传递数据给爷爷组件,需要通过provide一个函数的方式实现

  1. 爷爷组件传递一个函数,后续通过函数的形参获取数据
  2. 孙子组获取并调用该函数传递数据

相当于爷爷组件提供了一个盒子,然后把盒子扔给了孙子组件,孙子组件把要传的数据装到盒子里,然后爷爷组件通过形参收到

文章分类
前端
文章标签