Vue — 组件通信(一)
最后更新于:2022-04-02 08:08:40
[Toc]
>[success] # 组件通信
~~~
1.常见的组件通信方式使用'props'父传子,使用'$emit' 子传父,使
用'bus'/'vuex' 实现兄弟组件通信,使用一些特别的方式例如'ref','$parent'
,'$children'。
2.另外一种不常见的,组件的通信 'provide / inject',这种通信和'vuex','bus'
不同,它是一种vue.js 内置的接口
3. 'provide / inject' 和'props' 不同点是'props' 只能进行父子之间的传值,
简单的说就是一层,但如果想爷孙传值就不行,爷孙直接的可以使用
'provide / inject' 可以理解是一个加强版本的'props',但做不到兄弟组件通信
,兄弟间还是需要使用'bus' 和'vuex' ,但是也有其他办法利用 'provide / inject'实现
4.provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了
一个可监听的对象,那么其对象的属性还是可响应的
~~~
>[info] ## 使用provide / inject
官网讲解
~~~
1.解释单词意思方便更好的理解 ,provide -- 提供 , inject -- 注入
2.官方文档不推荐使用,但是iview作者给出的建议是可以好好利用让其变得强大。
3.'provide:Object | () => Object'
'inject:Array | { [key: string]: string | Symbol | Object }'
官方给的两个参数接收的值,其中provide 支持对象和一个方法返回对象
,下面的案例将对这个详细讲解
~~~
>[danger] ##### provide 对象形式使用
* 下面代码实现效果:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/9d8110772b38e1d36b9fe09362c903ba_213x32.png)
~~~
1.使用'provide' 对象的形式,注意如果使用对象的形式,是无法获得当前
,组件的'this'指向因此也无法获取其中的data
2.下面案例中 'Acomponents' 组件中嵌套了'Bcomponents',在一个视图组
件中去调用'Acomponents' 这样这个视图和'Bcomponents' 形成了爷孙关系
~~~
* Acomponents.vue 组件中
~~~
~~~
* 组件 Bcomponents 写法
~~~
~~~
>[danger] ##### provide 使用方法返回对象
* 代码效果图
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/6dedfc7c1f4d8b2d43f8ef52c9f14581_293x40.png)
~~~
1. 'provide' 在刚才案例中使用对象的形式传入this,会报错但是不能传递
固定值,为了让代码更灵活,使用方法返回对象的形式如下代码。
~~~
* Acomponents.vue 组件中
~~~
~~~
* 组件 Bcomponents 写法
~~~
~~~
>[danger] ##### provide技巧
~~~
1.在文章开头就说了'provide 和 inject 绑定并不是可响应的。这是刻意为之
的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应
的'简单的说父组件提供给子组件的内容,当父组件再次改变数据的时候,
子组件是收不到的,并且子组件也无法更改父组件传递的值
2.但是官方的这句话也说了,如果是一个可监听的对象就可以,这样就有一
个解决方法,就是父组件在提供属性值的时候提供的参数是对象,或者是
当前的this本身
3.在vue2.6版本提供了一个'Vue.observable' 来帮忙解决如果传递一个this过
于浪费,和如果传递必须要把数据变成对象的形式的尴尬
~~~
* 父组件
~~~
~~~
* 子组件
~~~
~~~
* 开始案例利用provide 方法的形式返回app.vue this执行,让全局组件获取 到登陆信息
~~~
~~~
* 接下来,任何组件(或路由)只要通过 inject 注入 app.vue 的 app 的话,都可以直接通过 this.app.xxx 来访问 app.vue 的 data、computed、methods (下面代码还是写在app.vue文件中的)
~~~
~~~
* 在组件中或者其他视图组件中获取(userInfo 信息)
~~~
';
我接受爷爷组件的传值{{name}}
~~~
* 调用组件Acomponents 的视图组件写法
~~~
我接受爷爷组件的传值{{name}}
~~~
* 调用组件Acomponents 的视图组件写法
~~~
我接受爷爷组件的传值{{dataName.name}}
~~~
>[info] ## 根据案例衍生
~~~
1.思考什么时候可以利用这个属性?如何利用这个属性可以达到最佳
2.答:当我们封装一个select 标签的时候,我们将select 和里面的opition,
拆成两个组件去写和维护,这时候'opition' 组件想获取'select' 组件的值时候
,可以利用这个或者'props' 来传递
3.答:如何达到最佳,当我们使用'provide' 时候使用方法返回对象可以传递
一个this,如果我们直接将祖先组件的'this' 传递过去,就会发现在子孙组件
中就可以去调用祖先组件的中的内容
~~~
>[danger] ##### 关于问题一种select 组件
直接参考简书文章
>[danger] ##### 利用问题二的特性做一个Vuex
~~~
1.下面的案例不是为了替代Vuex,只是一种方案来实现Vuex
2.根据cli搭建的项目,我们可以发现'app.vue'实际上是所有的根,而且
app.vue 是整个项目第一个被渲染的组件,而且只会渲染一次(即使切换路
由,app.vue 也不会被再次渲染),利用这个特性,很适合做一次性全局的
状态数据管理
3.尝试写一个全局登陆用户信息案例
~~~
* 首先下面代码是对第二条的解释(常见的app.vue一般只有一个router-view)
~~~
{{ app.userInfo }}
~~~
* 如果某个组件中改变从app中的值,需要全局统一的时候可以这么做,更改对应app.vue中的值
~~~
{{ app.userInfo }}
~~~