什么是组件间的通信
多个组件间的数据的相互传输和共享
为什么回出现这种问题
在使用 vuejs 组件进行开发的时候,我们的页面不可能只使用一个组件,肯定是各个组件组合使用,每个组件都有自己的 data ,但是它们有不可能是单独存在,肯定要和其他组件进行数据的交流,我们把这种组件之间进行的数据传递共享称之为组件间的通信问题
vuejs 组件间的通信一般有以下几种:
1::父子之间的通信
2:子父之间的通信
3:爷孙之间的通信
4:孙爷之间的通信
5:兄弟之间的通信
通信的手段
1:属性传递:主要用在父子通信之间
2:事件监听和事件触发(发布和订阅模式):主要用在子父之间的通信
3:eventBus:主要实现兄弟间的通信,子父间的通信也可以使用
4:ref 和 $parent
5:vuex(后期的重点)
下面我们来一个一个看
属性传递
属性传递一般用在父子通信之间,既然是父子通信,那么肯定有嵌套,我们把根组件作为父级,现在我们要把父组件里的 msg 传给子组件,利用属性传递
<div id="box">
<h1>我是父组件</h1>
//1:在孩子的标签上自定义一个属性,父亲通过属性传递,把模型变量给到儿子
//也就是说子组件的属性可以获取父组件的模型变量
<son :fromfather="msg"></son>
</div>
<script>
//定义一个子组件
var son = {
data: function(){
return {
title: '我是子组件'
}
},
//2:在孩子对象的 props 属性里面,定义好标签里声明的属性,类似于局部组件的模型变量,属性值就是从父组件那里拿过来的信息
props: ['fromfather'],
template: `
<div>
<h2>{{ title }}</h2>
<p>这是从我父亲那里拿到的信息:{{ fromfather }}</p>
</div>
`
}
var vm = new Vue({
el: "#box",
data: {
title: 'component',
msg:'给我孩子的信息'
},
//定义局部组件
components: {
son
}
})
</script>
总结:属性传递就是把父亲的信息当做孩子的属性值(这个属性是我们自定义的),然后我们在 props 里定义好我们自定义的属性,这个属性值就是我们需要的父亲的信息
事件监听和事件触发(发布和订阅模式)
事件监听和事件触发(发布和订阅模式)一般用在子父通信(父子通信也可以用,但是父子通信用属性传递会简单的多),它有三步
- 需要在子组件调用处设置自定义的事件
- 需要在父组件里面定义好自定义事件的回调函数
- 需要在子组件里面触发第一步定义自定义事件,同时传递数据,这样完成的子父通信。
<div id="box">
<h1>我是父组件</h1>
<p>这是我的孩子给我的信息:</p>
//1:在子组件调用处设置自定义事件-->
<son @tofather="eventHanler"></son>
</div>
<script>
var son = {
data: function(){
return {
title: '我是子组件',
msg: '这是给父亲的信息'
}
},
methods: {
//3:在子组件里触发第一步自定义的事件
start: function(){
this.$emit('tofather','father');
}
},
template: `
<div>
<h2>{{ title }}</h2>
<button @click="start">把我 msg 里的内容发给父亲</button>
</div>
`
}
var vm = new Vue({
el: "#box",
data: {
title: 'component'
},
components: {
son
},
methods: {
//2:在父组件里定义好子组件的回调函数
eventHanler: function(data1){
console.log(data1);
}
}
})
</script>
总结:子组件自定义事件的回调函数放在父组件里面执行,然后在子组件里面触发自定义的事件,并把要给父亲的数据也传过去,这时候在父组件里的回调函数就可以接受子组件的数据并把它放到自己的模型变量中去
eventBus
主要是用来进行兄弟之间通信的
- 实例化一个 Vue 实例对象
- 在需要接收数据的地方进行事件的监听(被动)(事件的名称完全用户自定义,不要系统的传统)
- 在需要传递数据的地方触发第二步定义的事件(主动)
<div id="box">
<bigbrother></bigbrother>
<littlebrother></littlebrother>
</div>
<script>
//1:实例化一个 Vue 实例对象
var EventBus = new Vue()//事件车
//大哥
var bigbrother = {
data: function(){
return {
title: '我是大哥',
msgToLittle: '最近怎么样'
}
},
methods: {
clickLittle: function(){
EventBus.$emit('toLittle',this.msgToLittle)
}
},
//在需要传递数据的地方触发第二步定义的事件
template: `
<div>
<h2>{{ title }}</h2>
<button @click="clickLittle">给小弟发消息</button>
</div>
`
}
//小弟
var littlebrother = {
data: function(){
return {
title: '我是小弟',
msgfrombig: ''
}
},
created: function() {
//2:在需要接收数据的地方进行事件的监听(被动),因为要一直监听,所以写在 created 里
//参数1:监听的事件,自己定义,不要和系统的有冲突就行
//参数2:从监听事件中传过来的数据
EventBus.$on('toLittle',data=>{
this.msgfrombig = data;
// console.log(data)
})
},
template: `
<div>
<h2>{{ title }}</h2>
<p>这是大哥给我的消息:{{ msgfrombig }}</p>
</div>
`
}
var vm = new Vue({
el: '#box',
data: {
title: '我是根组件'
},
components: {
bigbrother,
littlebrother
}
})
</script>
总结:他可以看做是利用 EventBus 来做事件监听和事件触发,通过
EventBus.$emit
来触发 接收数据方的监听事件并把数据传过去,接收方监通过EventBus.$on
来监听事件并获取数据,从而实现数据的传递(其实这个也可以用于父子之间的通信)
ref 与 $parent
ref:在 vuejs 里面作者不建议进行 DOM 操作,把 DOM 操作都换成指令,但是不代表我们就不能用 DOM 操作,ref 是 reference 引用 DOM操作 父子通信
我们先通过一个例子来看一下 ref 的作用
<div id="box">
<!--ref 的值,我们自己定义,他就相当于定义了一个模型变量-->
邮箱:<input type="text" ref="email">
<br />
<button v-on:click="clickHandler">点击获取信息</button>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
title: "parent",
},
methods: {
clickHandler: function(){
console.log(this.$refs);//this.$refs 这个属性包含了所有使用了 ref 这个属性的 DOM 节点
console.log(this.$refs.email.value);//通过 DOM 节点的操作我们可以获取输入框里的值
}
}
})
</script>
我们知道了在 this.$refs 里面包含了所有引用 ref 属性的 DOM 元素,接下来我们就用他来进行一下父子通信
<div id="box">
<h1>父组件</h1>
<button @click="clickHandler">获取子组件的值</button>
<p>这是从子组件获取的值:{{ msgfromSon }}</p>
//ref 一定要设置在 son 上面,这样才能被父组件监测到,相当于获取了 son 这个DOM 元素节点
<son ref="myson"></son>
</div>
<script>
var son = {
data: function(){
return {
username: ''
}
},
template: `
<div>
<h2>子组件</h2>
账号:<input type="text" v-model="username">
</div>
`
}
var vm = new Vue({
el: "#box",
data: {
title: "refs",
msgfromSon: ''
},
components: {
son
},
methods: {
clickHandler: function(){
this.msgfromSon = this.$refs.myson.username
// console.log(this.$refs.myson.username);
}
}
})
</script>
我们还可以用 $parent 来获取父节点,我们用 $parent 就可以进行 子父 之间的通信
<div id="box">
<h1>父组件</h1>
<p>给儿子:<input type="text" v-model="father"></p>
<son ref="myson"></son>
</div>
<script>
var son = {
data: function(){
return {
username: '',
msgFromFather: ''
}
},
methods: {
clickHandler: function(){
// console.log(this.$parent.father)//获取到父组件节点了
this.msgFromFather = this.$parent.father
}
},
template: `
<div>
<h2>子组件</h2>e
<button @click="clickHandler">获取父亲的数据</button>
<p>这是从父亲哪里拿来的数据:{{ msgFromFather }}</p>
</div>
`
}
var vm = new Vue({
el: "#box",
data: {
title: "refs",
father: ''
},
components: {
son
},
methods: {
clickHandler: function(){
this.msgfromSon = this.$refs.myson.username
// console.log(this.$refs.myson.username);
}
}
})
</script>