20200506 Vue组件 组件通信

组件关系可分为:父子组件通信,兄弟组件通信,跨级组件通信

自定义事件---子组件给父组件传递数据

使用v-on 除了监听 DOM 事件之外,还可以用于组件之间的自定义事件。
子组件使用 $emit()触发事件,父组件使用 $on()监听子组件事件

第一步:自定义事件
第二步:在子组件中使用$emit 触发事件,第一个参数是要触发的事件名,后面的参数是要传递的数据
第三步:在自定义事件中用一个参数来接收

    <div id="app">
        你的银行卡余额是:{{total}}
        <son-component @change='handelTotal'></son-component>
        <!-- 自定义的change事件 -->
    </div>


    <script>
        Vue.component('son-component', {
            template: `<div>
                <button @click='addMoney'> +1000 </button>
                <button @click='minusMoney'> -1000 </button>
            </div>`,
            data: function () {
                return {
                    count: 2000
                }
            },
            methods: {
                addMoney() {
                    this.count = this.count + 1000
                    this.$emit('change', this.count)
                //触发change事件,并传递给它一个参数this.count
                },
                minusMoney() {
                    this.count = this.count - 1000
                    this.$emit('change', this.count)
                }
            }
        })

       let app = new Vue({
            el: '#app',
            data: {
                total: 2000
            },
            methods: {
                handelTotal(value) {
                    //此处的形参value 就是子组件传递过来的数据,即上面的 this.count
                    this.total = value
                }
            }
        })
    </script>
</body>

非父子关系组件之间的通信 --- 父链---子链

有时候两个非父子关系的组件也需要通信,在简单的场景下,可以使用一个空的 vue 实例作为中央事件总线(中介):

let bus = new Vue()
//bus 为自定义名称,非固定写法

//触发组件 a 中的事件:
bus.$emit('a-component',1)

//在组件 b 创建的钩子函数中监听事件
bus.$on('a-component',function(id){
   //......
 })

从组件a向组件b中传递数据,首先要在根组件中定义一个 bus 中介
在a组件中通过 this.$root.bus 拿到根组件中的 bus 中介,再通过this.$root.bus.$emit('lala',this.aaa)去触发一个事件,并传递一个数据。
然后在 b 组件中,通过钩子函数 createda组件创建的时候就通过this.$root.bus.$on('lala',function(value){}) 去监听这个lala事件


    <div id="app">
        <a-component></a-component>
        <b-component></b-component>
    </div>


    <script>
        Vue.component('a-component', {
            template: '<div><button @click="aHandle">点击我向B组件传递数据</button></div>',
            data() {
                return {
                    aaa: '我是A的内容'
                }
            },
            methods: {
                aHandle() {
                    //this.$root 表示的是根组件
                    this.$root.bbb.$emit('lala', this.aaa)
                }
            }
        })
        Vue.component('b-component', {
            template: '<div>我是B组件</div>',
            created() {
                //a 组件在创建实例的时候就监听事件--lala事件
                this.$root.bbb.$on('lala', function (value) {
                    alert(value)
                })
            }
        })


        let app = new Vue({
            el: '#app',
            data: {
                bbb: new Vue()
            }
        })
    </script>


父链、子链

父链:this.$parent

Vue.component('a-component', {
  template: '<button @click="setFatherData">通过点击我修改父组件的数据</button>',
  methods: {
      setFatherData() {
          //拿到父组件中的 msg ,对其进行修改
          this.$parent.msg = '数据已经修改了'
       }
  })


//父链的父链就是 this.$parent.$parent

子链:this.$children
提供了为子组件提供索引的方法,用特殊的属性ref为其增加一个索引

<div id="app">
   <a-component ref="a"></a-component>
   <b-component ref="b"></b-component>
   <c-component ref="c"></c-component>
   ---{{formChild}}
   <button @click="getChildData">我是父组件的按钮,点击我拿到子组件的内容</button>
</div>

    <script>
        Vue.component('a-component', {
            template: '<div>我是a组件</div>',
            data() {
                return {
                    msg: '我是a组件的内容'
                }
            }
        })
        Vue.component('b-component', {
            template: '<div>我是b组件</div>',
            data() {
                return {
                    msg: '我是b组件的内容'
                }
            }
        })
        Vue.component('c-component', {
            template: '<div>我是c组件</div>',
            data() {
                return {
                    msg: '我是c组件的内容'
                }
            }
        })


        let app = new Vue({
            el: '#app',
            data: {
                formChild: '还未拿到内容'
            },
            methods: {
                getChildData() {
                    //这个方法用来拿子组件中的内容,但是子组件不止一个
                    //所以用到 ref 属性为子组件加一个索引
                    //在需要拿到子组件的内容时直接通过 this.refs.索引名 就可以了
                    this.formChild = this.$refs.c.msg
                }
            }
        })
    </script>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353