遇到问题首先要查官方文档
https://v2.cn.vuejs.org/v2/guide/components-edge-cases.html
文档能首先解决60% - 80%的问题。
0.了解子组件与父组件的关系
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
父beforeUpdate->子beforeUpdate->子updated->父updated
父beforeUpdate->父updated
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
导入子组件
1.父组件调用子组件内容【一对一】
首先这个一对一表示的是一个父组件下同名的只有一个子组件。【即子组件不可以被v-for包围】
1.1 父组件调用子组件的methods
-
指定名称,ref是组件标签自带的一个属性,直接写就好了,表示被引用【reference】时的名称。 -
在js栏中调用子组件的方法,$refs是Vue对象的一个实例属性,存储当前vue对象中所引用的组件标签。我们刚刚指定了子组件的名称,直接对应然后就可以调用该名称组件内部的方法了。
2.子组件调用父组件内容【一对一】
一个子组件只有一个父组件
2.1 子组件调用父组件的methods
子组件直接使用this.$parent.xxx()即可,注意方法名是其父组件要已经定义的。
在一对一的父子通信下,该方法更加简单。当然有另一种方法是使用$emit,下面的多对一中会讲到。
2.2 子组件调用父组件的属性
-
指定名称,即指定ref -
先进入子组件,子组件中指定需要的变量的名称,指定字符串名称即可,因为只作为该组件的属性名!同时要注意,props是一个数组,而且是官方指定的vue实例的一个属性,所以其级别是和methods和data是同级的,不要放到里面去了。而且这个是在子组件中定义! -
在进入父组件,对于子组件需要访问的变量,我们直接双向绑定,属性名与子组件的props数组中定义的一致,而绑定的对象就是父组件的属性变量,可以是如图的v-for的对象,也可以是data中的变量对象。【如果出错了,检查自己是不是加了this.属性,一律不要加this.属性, 直接输入变量名就好了】
如图:【先别看@loadComments,下面会介绍】
- 进入子组件,直接使用变量item
3.父组件调用子组件【一对多】
一个父组件下有多个同名子组件。如图,通过v-for后,名为Comments的组件在当前父组件中可就不止一个了。
3.1 父组件调用子组件的methods
- 从理论上确实可以,但是实际上,我尝试这样去获取的时候,发现这个容器【应该是个set】中的元素是无序的,我每次获取Comment[0],得到的vue对象都时不一样的。如图:
- 所以如果是在v-for下的情况,是不可以使用
this.$ref.xxx[i] 来获取子组件对象的 - 并且官方文档也警示我们,不要在v-for的场景下使用$refs获取子组件。
- 解释一下官方文档。v-for和v-if一样,指令都是响应了数据变化再渲染的。而如果对数据的修改不是响应式的,那么v-for和v-if就不会自动重新渲染,即使数据变更了。比如你发表了一个帖子,如果对数据进行非响应式修改,那么页面不会出现新帖子的数据。
- 所以$refs访问子组件是一种非响应式访问,应该避免在需要响应式的场景中使用。
- 因此!在响应式场景【v-for、v-if】目前不建议父组件去调用子组件的方法,本来就可以单独交给子组件做的就在子组件中完成。
- 也不建议使用
this.$ref.xxx[i] ,因为对于索引来说会失控
解决方向参考:
- 最优的解决方向是,对于子组件自己完成该功能所需要的参数,由父组件提供【即指定props数组】即可,由子组件自己完成自己的方法。父组件尽量不要去调用子组件的方法。
- 比如说把触发响应时间的DOM从父组件剥离去到子组件,避免父组件响应然后去调用子组件。
4.子组件调用父组件【多对一】
即多个同名子组件对应一个父组件。
4.1 子组件调用父组件的属性
与**子组件调用父组件的属性【一对一】**一致,使用props数组
4.2 子组件调用父组件的methods
- 同子组件要访问属性一样,变量数据是双向绑定,那调用方法就是一个事件
- 但是要注意,目前对于子组件的事件,不需要像props数组一样提前定义
- 首先我们进入父组件,对子组件对象添加一个触发事件,事件名称与要调用的父组件方法同名即可,如图的loadComments
- 然后我们进入子组件,再需要使用父组件方法的地方使用
e
m
i
t
属性,其语法规则为
‘
t
h
i
s
.
emit属性,其语法规则为`this.
emit属性,其语法规则为‘this.emit(事件名,参数1,参数2,…)`,只需要第一个参数是事件名即可,其余的参数个数不定,根据父组件方法的参数个数进行传参。
总结【一般使用】
-
父调用子
- 父组件调用子组件的属性:一般不会调用
- 父组件调用子组件的方法:使用$refs.子组件的ref名.方法名调用
-
子调用父
- 子组件调用父组件属性:先在子组件中定义props数组指明数据名,然后在父组件中对子组件标签进行双向绑定。
- 子组件调用父组件方法:
- 子组件直接使用this.$parent.方法名调用
- 父组件中对子组件标签进行事件绑定父组件的方法,然后子组件中使用$emit()方法触发事件
-
如果父子通信出现在v-for的场景下
- 父组件无法调用子组件的方法,因为$refs的索引不可控
- 子组件调用父组件方法不可以使用非响应式的this.
p
a
r
e
n
t
.
方法名,而需要使用
parent.方法名,而需要使用
parent.方法名,而需要使用emit
- 子组件调用父组件的属性的方式不变
|