参考文章:
Vue2.0子同级组件之间数据交互
1、父组件可以使用 props 把数据传给子组件。
2、子组件可以使用 $emit 触发父组件的自定义事件。
(一)父组件给子组件传值,关键字:props
父组件:
<template> <div> <h1>父组件</h1>
<!-- 引入子组件 --> <child :sendMsg="fatherMsg"></child> </div> </template> <script> import child from '@/components/child' export default { name: 'father', components: { child }, data() { return { fatherMsg: '嗨,儿子' // 传递给子组件的值 } } } </script>
子组件:通过props拿到父组件传递过来的值
<template> <div> <h1>子组件</h1> <span>获取父组件传值:{{sendMsg}}</span> </div> </template> <script> export default { name: 'child', data() { return { } }, props: ['sendMsg'] // 拿到父组件绑定到sendMsg的值,然后在子组件下显示出来 } </script>
(二)子组件给父组件传值:通过触发事件传递值
以上面的示例代码作为基础修改,子组件:
<template> <div> <h1>子组件</h1> <span>获取父组件传值:{{sendMsg}}</span><hr> <button @click="sendToFather">子组件给父组件传值</button> </div> </template> <script> export default { name: 'child', data() { return { childMsg: '这是来自子组件的数据' } }, props: ['sendMsg'], methods: { sendToFather: function() { this.$emit('getChildValue', this.childMsg); // 参数1 getChildValue作为中间状态,参数2 this.childMsg即为传递给父组件的数据 } } } </script>
父组件:
<template> <div> <h1>父组件</h1> <!-- 引入子组件 定义一个on的方法监听子组件的状态,然后通过getChild方法获取子组件传递的数据--> <child :sendMsg="fatherMsg" v-on:getChildValue="getChild"></child> <span>这是来自子组件的数据:{{childValue}}</span> </div> </template> <script> import child from '@/components/child' export default { name: 'father', components: { child }, data() { return { fatherMsg: '嗨,儿子', childValue: '' } }, methods: { getChild: function(data) { // 此时的参数data为子组件传递的值,即this.$emit()的第二个参数 this.childValue = data; } } } </script>
(三)同级组件传递数据
对于同级组件传值用的较多的情况,推荐直接使用vuex进行状态管理会比较方便。
补充:面试被问到同级组件传递参数,平时很少去用这个,没答上来(尴尬),回来百度了下,原来就是通过一个中间桥接的方式进行传递(遭不住,之前看到过,没引起重视)
其原理是先建立一个中间事件总线center.js,放在tools文件夹下,如下:
import Vue from 'vue' export default new Vue()
center.js中我们只创建了一个新的Vue实例,以后它就承担起了组件之间通信的桥梁了,也就是中央事件总线
然后创建第一个子组件first.vue:
<template> <div class="first-vue-box"> <p>this is firstChild vue</p> <button @click="sendMsg">发送</button> </div> </template> <script> import bridge from '../tools/center' export default { data () { return {} }, methods: { sendMsg () { bridge.$emit('firstChildMsg', 'this is firstChild Msg') } } } </script> <style lang="scss" scoped> .first-vue-box { border: 1px solid blue; } </style>
这里先引入事件总线,通过事件总线点击按钮后将first.vue的信息通过事件firstChildMsg的形式发布出去了(我个人的理解是相当于通过事件总线,将first.vue的firstChildMsg这个事件暴露出去),用法跟子组件向父组件传参的模式一样
然后再创建第二个组件second.vue:
<template> <div class="second-child"> <h4>this is second child vue</h4> <p>从first.vue获取同级组件传递过来的信息:{{message}}</p> </div> </template> <script> import bridge from '../tools/center' export default { data () { return { message: '默认值' } }, mounted () { let _this = this bridge.$on('firstChildMsg', function (msg) { _this.message = msg }) } } </script>
在second.vue中再引入事件总线,然后通过$on(functionName, callback)监听first.vue暴露出来的firstChildMsg事件,通过回调函数获取first.vue传递出来的值(我个人是这么理解的)
引入两个子组件:
<template> <div class="detail-div"> <h3>首页详情</h3> <first-child></first-child> <second-child></second-child> </div> </template> <script> import firstChild from './first' import secondChild from './second' export default { data () { return {} }, components: { firstChild, secondChild }, mounted () { // console.log('详情页面...') } } </script>
第二个子组件通过中央事件总线bridge,监听事件first.vue发布的事件firstChildMsg,获取到子组件first.vue发送过来的信息,如下图所示:
点击发送按钮后second.vue获取到first.vue传递过来的值:
之前在项目中没这样用过同级组件之间的传值,这次是个教训,以后得注意一下每一个细节的地方。这里我看了参考文章,自己写个示例来验证的,最好是能自己验证一下,记忆才比较深刻。