爱客仕-前端团队博客园

vue2父子组件间相互通信

嗨,又见面了,这次大致介绍一下vue2中父子组件间相互通信的方式,因为vue2中取消了$dispatch() 派发事件和 $broadcast() 广播事件

仅剩下两个事件

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

一、父组件触发子组件内部事件

第一种,我把它命名为“儿子偷听”

父组件触发parentMsg事件

1
this.$emit('parentMsg', '回来打断腿')

子组件中通过this.$parent.$on来监听父组件触发的事件,同时获取父组件中传过来的值

1
2
3
this.$parent.$on('parentMsg', (res) => {
// res为'回来打断腿'
})

儿子通过偷听家里老爹说话,来决定是回家还是出家…

二、子组件触发父组件内部事件

第一种,我把它命名为“儿子闹事”

儿子到他爸家闹事
子组件中触发

1
this.$parent.fight('来啊 造作啊 反正有大把风光')

儿子闹事老子当然要教训这个不孝儿子
父组件就会触发fight事件
父组件中

1
2
3
4
5
methods: {
fight (res) {
// res为'来啊 造作啊 反正有大把风光'
}
}

假如是子组件的子组件呢?

儿子当然也可以去他爷爷家闹事
孙子组件中通过this.$parent.$parent.fight('来啊 造作啊 反正有大把风光')
爷爷当然也要教训不孝孙子
爷爷组件就会触发fight事件

为什么是用$parent找父组件,而不用$children来找子组件去监听子组件或者触发子组件中的事件呢?
因为$children是个数组,不好定位到具体哪个子组件
$parent对于子组件来说是唯一的,儿子只有一个爹,当然他爹有可能有好几个分身,分身等同于真身

第二种,跟vue1.x中使用的方式一样

通过在子组件标签属性上加上v-on来监听子组件
首先子组件中通过$emit来触发child-msg事件

1
this.$emit('child-msg', '456')

当子组件触发了child-msg事件,父组件监听到子组件触发了child-msg,就会触发父组件handleIt事件

父组件中

1
<child v-on:child-msg="handleIt"></child>

1
2
3
methods: {
handleIt (res) {}
}

三、prop

引用一下vue官网对props的介绍

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。
另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop 。如果你这么做了,Vue 会在控制台给出警告。
通常有两种改变 prop 的情况:

  1. prop 作为初始值传入,子组件之后只是将它的初始值作为本地数据的初始值使用;
  2. prop 作为需要被转变的原始值传入。

意思是我们不能在子组件中直接对prop的值进行修改,需要用data或computed换个马甲,如果直接修改prop的值,vue会报错。
前提是这个prop的值不是对象或者数组,因为对象或者数组是引用类型,即使用data或computed换个马甲,在子组件中修改马甲的值,父组件中的值也会跟着修改,虽然vue不会报错,但是也会让应用数据流难以理解。所以最好不要在子组件中对对象或者数组类型的prop进行修改。

  1. data

    1
    2
    3
    4
    props: ['oldData'], // 非对象或数组类型
    data () {
    return { newData: this.oldData }
    }

    不能直接对oldData进行修改,可以对newData进行修改

  2. computed

    1
    2
    3
    4
    5
    6
    props: ['oldData'], // 非对象或数组类型
    computed: {
    newData () {
    return this.oldData.trim().toLowerCase()
    }
    }

    不能直接对oldData进行修改,可以使用computed对oldDate进行改造

另外,子组件也可以直接修改父组件中data的值,但是并不推荐这种方式,同样也会导致数据流难以理解
假设父组件有

1
2
3
4
5
data () {
return {
isShow: true
}
}

子组件直接修改父组件中isShow的值

1
this.$parent.isShow = false

四、v-model

v-model是vue中表单元素进行双向绑定时使用的
在vue2中取消了props.sync双向绑定,但是可以直接在子组件上使用v-model,比如:
父组件中

1
<child v-model="msg"></child>

1
2
3
4
5
data () {
return {
msg: ''
}
}

子组件child

1
this.$emit('input', 123)

当子组件执行this.$emit('input', 123),就可以将123传给父组件的msg

更多的通信方式,欢迎大神补充…