vue 父链和子组件索引_vue组件详解(三)——组件通信

本文详细介绍了Vue中组件之间的通信方式,包括自定义事件用于父子通信,v-model实现数据双向绑定,非父子组件间通过事件总线bus进行通信,以及使用父链和子组件索引直接访问组件。强调了最佳实践,建议避免子组件直接修改父组件数据。
摘要由CSDN通过智能技术生成

组件之间通信可以用下图表示:

组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信。

一、自定义事件

当子组件需要向父组件传递数据时,就要用到自定义事件。

子组件用$emit ()来触发事件,父组件用$on()来监昕子组件的事件。

父组件可以直接在子组件的自定义标签上使用v-on 来监昕子组件触发的自定义事件,如:

总数:{{total}}

Vue.component('my-component9',{

template: '

' +

' +1' +

' -1' +

'

',

data: function(){

return {

count: 0

}

},

methods:{

increase: function(){

this.count++;

this.$emit('add',this.count)  //广播的事件名和数据

},

reduce: function(){

this.count--;

this.$emit('cut',this.count)  //广播的事件名和数据

}

}

});

var app9 = new Vue({

el: '#app9',

data:{

total: 0

},

methods:{

getTotal: function(count){

this.total = count;

}

}

});

二、使用v-model

Vue2 .x 可以在自定义组件上使用v-model 指令,直接看一个事例:

总数:{{total}}

  //这个地方v-model实际是一个语法糖,可以直接理解为接收到广播input里面的数据(this.total=count)。

Vue.component('my-component10',{

template: '

' +

'+1' +

'-1' +

'

',

data: function(){

return {

count: 0

}

},

methods:{

increase: function(){

this.count++;

this.$emit('input',this.count)  //注意这个地方,广播的事件名称为特殊的input

},

reduce: function(){

this.count--;

this.$emit('input',this.count)  //注意这个地方,广播的事件名称为特殊的input

}

}

});

var app10 = new Vue({

el: '#app10',

data:{

total: 0

}

});

v-model 还可以用来创建自定义的表单输入组件, 进行数据双向绑定,例如:

总数:{{total}}

-1

Vue.component('my-component11', {

props: ['value'],  //使用v-model的表单组件时,父组件通过value来进行传值

template: '',

methods: {

updateValue: function(event){

this.$emit('input', event.target.value);

}

}

});

var app11 = new Vue({

el: '#app11',

data:{

total: 0

},

methods:{

reduce: function(){

this.total--

}

}

});

父组件的total发生变化时,会通过传递value值,影响子组件input中的value值,而子组件改变自己input中的value值,又会广播给父组件,影响父组件中的total值。

实现这样一个具有双向绑定的v -model 组件要满足下面两个要求:

•接收一个value 属性。

• 在有新的value 时触发input 事件。

三、非父子组件通信

在Vue . 2.x 中, 推荐使用一个空的Vue 实例作为中央事件总线( bu s ),也就是一个中介。

直接看一个事例:

{{message}}

var bus = new Vue();

Vue.component('my-component12',{

template: '传递事件信息',

methods: {

updateMessage: function(){

bus.$emit('updateMessage','更新我的组件信息'); //利用中介bus传播事件

}

}

});

var app12 = new Vue({

el: '#app12',

data:{

message: ''

},

mounted: function(){

var _this = this; //这一步赋值必须有

bus.$on('updateMessage',function(data){ //利用中介bus接收事件

_this.message = data;

})

}

});

在app 初始化时,也就是在生命周期mounted 钩子函数里监听了来自bus 的事件updateMessage(mounted挂载这一步相当于在两个组件直间提前安排了一个中介,当两个组件通信时,就可以通过该中介相互传递消息了) ,

而在组件my-component12中,点击按钮会通过bus 把事件updateMessage发出去,此时app 就会接收到来自bus 的事件,进而在回调里完成自己的业务逻辑。

这种方法巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级,而且Vue 1.x 和Vue 2.x 都适用。

四、父链与子组件索引

除了中央事件总线bus 外,还有两种方法可以实现组件间通信:父链和子组件索引。

在子组件中,使用this.$parent 可以直接访问该组件的父实例或组件,父组件也可以通过this.$children 访问它所有的子组件,而且可以递归向上或向下无线访问, 直到根实例或最内层的组件。

4.1父链

{{message}}

Vue.component('my-component13',{

template: '通过父链直接修改数据',

methods: {

updateMessage: function(){

this.$parent.message = '来自组件my-component13的内容'  //通过this.$parent直接修改父组件的内容

}

}

});

var app13 = new Vue({

el: '#app13',

data:{

message: ''

}

});

尽管V ue 允许这样操作,但在业务中, 子组件应该尽可能地避免依赖父组件的数据,更不应该去主动修改它的数据,因为这样使得父子组件紧藕合,理想情况下,只有组件自己能修改它的状态。

4.2 子组件索引

当子组件较多时, 通过this.$children 来一一遍历出我们需要的一个组件实例是比较困难的,尤其是组件动态渲染时,它们的序列是不固定的。Vue 提供了子组件索引的方法,用特殊的属性ref来为子组件指定一个索引名称。

{{message}}

通过ref获取子组件实例

Vue.component('my-component14',{

template: '

子组件
',

data: function(){

return {

message: '子组件内容'

}

}

});

var app14 = new Vue({

el: '#app14',

data:{

message: ''

},

methods: {

handleRef: function(){

this.message = this.$refs.com14.message; //通过$refs获取子组件实例

}

}

});

在父组件模板中,子组件标签上使用ref 指定一个名称,井在父组件内通过this.$refs 来访问指定名称的子组件。

$refs 只在组件渲染完成后才填充,并且它是非响应式的. 它仅仅作为一个直接访问子组件的应急方案,应当尽量避免在模板或计算属性中使用$refs。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值