vue3和vue2 之 provide/inject 用法区别 ---vue3组件间通讯2

一、为什么用他们?

 provide/inject 主要用于父组件和子孙组件间通讯,不用在父传子,子传孙,孙传重孙等数据传递了(解决了Prop 逐级透传问题)。简单的父子组件间传值还是使用props、emits或是defineProps、defineEmits、defineExpose比较方便。

二、原理 与 区别

父组件中提供数据,并在其后代的组件树,无论层级有多深,都可以中注入这些数据,从而实现了组件之间的数据传递。。

1. 在vue2中,组件实例方法和属性的继承是通过原型链来实现。

  • 当一个组件通过 provide 提供数据,它会将这些数据添加到其原型链上,然后子组件通过 inject 可以在原型链上查找并访问这些数据。
  • vue 会遍历父组件链,通过匹配provide( key,value)和inject(key,default [可选])的 key 来确定所提供的值。如果父组件链上多个组件对同一个 key 提供了值,那么离得更近的组件将会“覆盖”链上更远的组件所提供的值。如果没有能通过 key 匹配到值,inject() 将返回 undefined,除非提供了一个默认值。

2. 在 Vue 3 中 组件不再依赖于原型链,而是 引入了 Composition API,直接导出给组件实例。

  • provide 是在父组件中使用的选项,它是一个函数,会在父组件实例上创建一个名为 _provided 的对象。_provided 对象存储了提供给子组件的数据,而且这些数据会在整个组件树中可用,子组件可以通过inject选项来访问这些数据。
  • 当子组件访问通过inject注入的数据时,Vue 3会在组件树中向上搜索父组件,一旦找到包含提供数据的组件,Vue 3会从该组件的_provided属性中获取相应的数据。
  • 如果提供的数据是响应式的,子组件将自动成为这些数据的依赖,当提供的数据发生变化时,子组件将被通知并进行更新。 

三、使用方式

1. vue2中的使用

父组件:

// 1. 对象形式
export default{
 
 provide:{
 
  info:"哈哈哈"
 
 }
 
}

//2. provide 需要使用 data 内的数据(访问组件实例 property)时,需要将 provide 转换为返回对象的函数。
export default{
    data() {
        return {
            msg: "哈哈哈"
        };
    },
    provide() {
        return {
            info: this.msg //提供祖先组件的实例
        };
    },
}

后代组件:

// 1. 
export default{
 
 inject:['info'],
 
 mounted(){
     console.log("接收数据:", this.info) // 接收数据:哈哈哈
 }
 
}

//2. 或者 对象形式
<template>
  <div>
    <P>姓名:{{info.msg}}</P>
  </div>
</template>

<script>
export default {
 inject: {
  info: {
      from: 'info', // 当声明注入的默认值时,必须使用对象形式,与原注入名同名时,这个属性可选 
      default: 'default value'
  }
 } 
};
</script>

2. vue3中的使用

父组件:

//1. 
<script>
import { provide } from "vue"

export default {
  setup(){
    provide('info',"哈哈哈");

    provide('changeSubmitLoading', (val) => {
      submitLoading.value = val
    })
  }
}
</script>


// 2. 添加响应性
<script setup>

import { provide, ref } from 'vue'

const location = ref('哈哈哈')

function updateLocation() {
  location.value = '吼吼吼'
}

provide('location', {
  location,
  updateLocation
})
</script>

后代组件:

// 1. 
<template> 
 {{info}}
</template>

<template #cell="{ record }">
 <a-button size="mini" type="text"  @click="handleDelete(record)">
 </a-button>
</template>

<script>
import { inject } from "vue"
 
export default {
  setup(){
    const info = inject('info')
    const changeSubmitLoading = inject('changeSubmitLoading')
    
    const handleDelete = (record) => {
       /* 方法内其他内容*/  
       changeSubmitLoading(true)
    }

    return{
      info
    }
  }
} 
</script>

//2. 添加响应性后

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

<script setup>
import { inject } from 'vue'

const { location, updateLocation } = inject('location')
</script>


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值