title: 组件内父子小组件之间的通信
date: 2017-03-20
- vue组件
- 技术分享
分享组件内父子小组件间通信的一些个人理解。
组件内父子小组件之间的通信
有时制作一个大组件时需要我们将其拆分成多个小组件来完成,这就需要这些小组件之间进行数据通信。
父传子
父组件找到子组件的数据并对其控制。
找到子组件的数据
若不确定如何写才能找到该数据,则可以使用此方法:在父组件中写:
mounted(){
console.log(this)
}
页面重新加载后会在网页里的Console控制台中显示该组件的所有数据:
想找到子组件的数据,则展开上图中的$children:
,如想找到第一个子组件中的active
属性,鼠标悬浮在此属性上就可以看到代码:
此代码前加上this
就能得到第一个子组件的active
属性了。
控制子组件数据
由于this.$children
是个数组,所以想取所有子组件的同一个属性不能用this.$children.active
,而是要遍历数组再取,如:
methods:{
select(header){
if (header.liCss[1].disabled === false) {
let to = header.to;
let child = this.$children;
for (var i = 0;i < child.length;i = i + 1){
let _id = child[i].id;
if (_id === to){
this.$children[i].active = true;
this.headers[i].active = true
}else{
this.$children[i].active = false;
this.headers[i].active = false
}
}
}
}
}
如果子组件是传到父组件的slot
插槽中的,也可以用this.$slots.default
方法取到,若slot
有name
属性,把default
改为name
属性中定义的名字,该方法也是个数组。
子传父
子组件找到父组件的数据并对其传值。
找到父组件数据
只要该子组件的父组件仅仅只是你已知的且需要的父组件而不是未知的其他组件,则可以直接用this.$parent
取到父组件,由于父组件有且仅有一个,所以this.$parent
是一个对象而不是数组。
对父组件数据传值
如父组件的data()
中定义了一个空数组headers:[]
,则可以在子组件中用this.$parent.headers
方法取到此数组并且可以用push
方法对其传值,例:
mounted(){
if (this.isActive === true){
this.active = true
}
let _this = {title:this.title,to:this.id,active:this.active,liCss:this.liCss,aCss:this.aCss};
this.$parent.headers.push(_this)
}
v-for特例
有时会在父组件中写v-for
循环来添加多个具有相同属性的子组件,但这些子组件又有各自不同的样式,而这些样式又需要计算属性对其处理。
发现问题
对于这些样式或属性:
- 如果放在父组件的
props
和计算属性中处理,那么就会对所有的子组件的样式及属性进行同时控制,无法单独控制某个子组件,也无法让子组件们显示各自不同的样式及属性。 - 如果放在子组件的
props
中,然后传入到父组件,在父组件的计算属性中处理,也会产生上述问题。
解决问题
将这些样式和属性全部放在子组件的props
和计算属性中处理,然后将计算属性处理后的数据直接传给父组件就可以解决。例:
子组件中写:
props:{
disabled:Boolean,
'tab-header-line-color':{
type:String,
validator(value){
return isOneOf(value, ['','blue','red','yellow','white','themeprimary','themesecondary','themethirdcolor','themefourthcolor','themefifthcolor','snow','whitesmoke','seashell','ivory','platinum','lightgray','gray','darkgray','silver','sonic-silver','storm-cloud','lightcarbon','carbon','slate-gray','darkcarbon','info','sky','primary','azure','blueberry','palegreen','success','green','lightyellow','warning','gold','orange','lightred','darkorange','pink','darkpink','danger','magenta','purple','maroon'])
},
default:''
}
},
computed:{
liCss(){
return [
this.tabHeaderLineColor ? 'tab-' + this.tabHeaderLineColor : '',
{
'disabled' : this.disabled
}
]
}
},
mounted(){
let _this = {liCss:this.liCss};
this.$parent.headers.push(_this)
}
父组件中写:
{{header.title}}