一、父组件到子组件通信(子组件获取父组件数据)
1)属性名注册-props
弊端:如果是三层组件(或者更多)传递数据,那么即使第二层组件没有使用的属性为了给下一级组件传递也必须被注册,才可以使用
2)$attrs(推荐)
vm.$attrs内包含从根实例开始到该组件为止没有被注册的属性;解决了1)中出现的问题,但是弊端就是:会再html中显示这个没有在该组件使用的属性,可以在组件内加inherritAttr:false,解决该问题
<div id="wrapper">
<father-component :outertext="outertext" :innerText="innertext"></father-component>
</div>
<script>
const vm = new Vue({
el: '#wrapper',
data:{
outertext: '天气',
innertext: '多云转多云、小雨、25℃'
},
components: {
FatherComponent: {
props: ['outertext'],
created() {
console.log(this.$attrs.innertext)
},
inheritAttrs: false,//解决 由于使用$attrs会将没有在此组件内使用的属性展示在行间 的问题
template: `<div>
<h3>{{outertext}}</h3>
<son-component v-bind="$attrs"></son-component>
</div>`,
components: {
SonComponent: {
data() {
return {
}
},
props: ['innertext'],
template: `<h1>{{innertext}}</h1>`
}
}
}
}
})
</script>
注:这里的vm代表vue实例,下同
3)Vm.$parent、vm.$children(不推荐)
先获取父级、子级组件实例,在获取传递内容。弊端:若层级比较多使用起来很麻烦,比如this.$parent.$parent.$parent
this.$parent.outertext
4)Provide、inject(不推荐)
provide使用方法类似data,inject(译为注入)类似props
二、子组件到父组件通信(父组件获取子组件数据)
1)$children:
不推荐使用,在封装一些组件的时候可以使用
this.$children[0].msg
2)$refs——组件的引用:
既可以在dom元素中使用也可以在cmp组件中使用,this.$refs包含所有在该组件(dom元素)上的被引用的组件(dom元素)
<my-cmp @click='func' @mousedown='down' ref="dom" ></my-cmp>
//父组件中获取
mounted() {
console.log(this.$refs.dom.msg)//我是子组件中的数据msg
},
//子组件
myCmp:{
data() {
return {
msg:'我是子组件中的数据msg'
}
},
}
3)函数传参
通信原理:在父级中定义函数接收参数并在子组件执行函数并传参
如何让子组件拿到父组件中定义的函数?
a.可参照父组件到子组件通信中的属性传递一层层传到子组件
b.组件绑定事件,通过子组件触发事件(但自定义组件的不会自动监听到事件的触发,有以下方法解决该问题)
a. .native (给事件添加修饰符): 让定义的组件和原生dom同样具有监听事件触发的功能;
弊端:由于是给组件绑定的事件,点击组件的任何部分都会触发。
<my-cmp @click.native='func' ></my-cmp>
b. $listeners:组件的根元素不具备监听dom事件的触发,但根元素内部具备相应的监听dom事件的触发,
因此可以使用$listeners获取父组件传递过来的所有事件函数(再通过v-on绑定到对应的元素上即可)
用法:this.$listeners.click(this.msg)
c.$emit: 在子组件内部触发父组件监听的事件
this.$emit('click',this.msg)
三、兄弟组件间的通信(一个兄弟组件获取另一个兄弟组件内数据)
1)以兄弟组件的父亲作为媒介:
使用1、2中子传父、父传子传给相应兄弟组件,弊端:如果想给兄弟组件的子组件传递就会很麻烦
2)Event bus ——事件总线
实现兄弟元素的通信原理:借助一个新的Vue实例,在一个兄弟组件内使用$on向这个新的vue实例定义一个事件,在另一个兄弟组件内使用$emit触发该新Vue实例的事件。
定义新的Vue实例: Vue.prototype.bus = new Vue();
定义函数: this.bus.$on(‘click’,(options)=>{})
触发函数: this.bus.$emit(‘click’,options)
注:事件可以不为系统自带事件,但定义和触发的事件必须同名
四、父子间的双向通信
双向数据通信原理:首先给父组件绑定事件,子组件通过属性传递获取父组件的数据,将其保存在自己的data中,在子组件数据更改后,使用$emit触发父组件的事件,将更改后的数据作为参数传递给父组件,父组件在事件处理函数内对自己data内的数据进行更新,子组件的数据自然会跟随改变。
双向通信流程图: