多级父子组件的通信技术

        在一个实际的项目中,一个父组件可能有多层次结构的子组件体系。如果这个父组件要向第三层、第四层甚至更深的子组件传递数据,则要一级一级的通过自定义属性来实现,这显然降低了工作效率。

        Vue.js 3.x 框架提供了 Provide/Inject 功能来快速实现这种多级父子组件之间的通信技术。在这里,由父组件提供数据,所以父组件被称为“Provide”(供应方),子组件接收数据,所以最组件被称为“Inject”(注入方)。本节就带领读者学习Vue.js 3.x 框架新增的 Provide/Inject 功能。

一、Provide/Inject 的用法

        Provide 作为数据通信的提供者,可以在父组件的创建过程中使用 provide 选项,该选项取值为一个函数,与 data 数据区类似,将需要传递给子组件的数据作为该函数的返回值书写出来。

        Inject 作为数据通信的接受者,可以在子组件的创建过程中使用 inject 选项,该选项取值为一个数组, 数组元素是要用到的由父组件传递过来的变量名称,这些变量名都应该保证在父组件的 Provide 选项中出现过。

        【示例 4-19】Provide Inject 的使用。创建两个全局组件,组件名分别为 com-parent 和 com-child, 其中 com-parent 是 com-child 的父组件。在 Vue 应用实例的数据区声明变量,利用 Provide 与 Inject 技术让com-child 组件能够访问Vue 应用实例的数据区变量。

HTML 代码如下所示。

<div id="app">

        <com-parent>

                <com-child></com-child>

        </com-parent>

</div>

Vue 代码如下所示。

​
let app=Vue.createApp({
    data(){  
         return {
             studentName:'张三',
             studentInfo:{
                sex:'男',
                age:25
              }
          }
    },
    provide(){
        return {
            sName:this.studentName,
            sInfo:this.studentInfo
        }
    }
})
app.component('com-parent',{ template:`
<div class="parent">
<slot></slot>
</div>
`
})

app.component('com-child',{ template:`
<button @click="btnClick">我是 com-child 组件</button>
`, inject:['sName','sInfo'], methods:{
btnClick(){ console.log(this.sName);
console.log(this.sInfo.sex,this.sInfo.age);
}
}
})
app.mount('#app')

        在上述代码中,Vue 应用实例作为整个示例的父组件,com-parent 组件作为Vue 应用实例的子组件。同时 com-parent 组件又是 com-child 组件的父组件,com-child 组件是 com-parent 组件的子组件。Vue 应用实例需要将数据直接传递给 com-child 组件,中间间隔着 com-parent 组件。这种情况下,若按照组件树的结构一级一级传递数据,势必降低效率。这就需要用到 Provide/Inject 技术。

        第 11 行至第 16 行,Vue 应用实例使用 Provide 选项向所有子组件提供数据。第 29 行 com-child 组件接收两个由未知父组件传递过来的数据,分别是 sName 和 sInfo。

        读者可以尝试,com-parent 组件也可以读取Vue 应用实例提供的 Provide 数据。这就说明 Provide 提供的数据,任何一个层级的子组件都可以注入这些数据;反之子组件注入的数据无需知道是哪个层级的父组件提供的。这样大大提高了多级父子组件之间的通信效率。

二、Provide 数据的响应性

        默认情况下,通过 Provide/Inject 技术从父组件传递给子组件的数据并不是响应式的。也就是说如果父组件中修改了 Provide 提供的原始数据,则在通过 Inject 选项注入数据的组件中,注入的数据是不会实时变化的,依然是父组件修改之前的结果。

要想解决该问题,需要将父组件提供的代码和子组件注入的代码进行如下所示的修改。

        1、父组件 Provide 的数据需要分配一个组合式 API computed 属性。

        组合式 API 的 computed 属性采用 Vue.computed()方法来实现,该方法的参数是一个函数,函数使用return 将需要指定的数据返回。示例 4-19 的第 11 行至第 16 行代码应该改为如下所示的格式。

provide(){
    return {
        sName:Vue.computed(()=>this.studentName),
        sInfo:Vue.computed(()=>this.studentInfo) 15	}
	}

这样就可以响应式向子组件提供数据了。

        2、子组件在访问 Inject 注入的数据时必须使用 value 属性。

        子组件接收Provide 提供的数据时依然采用 inject 选项,同时依然取值为数组,将注入的变量名作为数组元素即可。但是在访问这些注入的数据时,必须使用 value 属性来得到提供的值。示例4-19的第 29 行至第 35 行代码应该改为如下所示的格式。

inject:['sName','sInfo'],
methods:{
    btnClick(){
        console.log(this.sName.value);
        console.log(this.sInfo.value.sex,this.sInfo.value.age);	
    }
}

        在上述代码中,第 33 行在注入的数据 sInfo 后面使用 value 属性,然后再连缀 sex 和 age 成员。这需要读者注意,若父组件 Provide 提供的数据是对象格式,则子组件在访问时需要先对注入的 Inject 变量使用 value 属性,然后再访问对象格式的内部成员。

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值