Vue04——组件之间的通讯

Vue里组件的通信

通信:传参、控制(A操控B做一个事件)、数据共享

!!!组件中的数据只能由组件其自身修改,所有方法最终操作数据的都是其组件自身!!!
  • 兄弟之间通信的话:viewmodel链 ref链 eventbus事件总线
  • 父亲—>子组件 props获取父亲传递来的数据 数据只能由自身更改!
  • 子组件–>父组件 1)父组件将更改自身数据的方法传递给子组件 2)事件触发与事件绑定的能力
模式:父子组件间、非父子组件

1、父组件将其自身操作数据的方法通过v-bind传递给子组件,子组件调用这个方法时,就可以给父组件传递数据

  • 这里父组件通过 :tell-dad=“change” 将其自身的change方法传递给子组件,子组件通过props来接收父组件传递过来的方法:props:[“tellDad”] (当遇到-减号的时候用驼峰写法)
  • 当子组件调用tellDad方法时,就会调用父组件的change方法,并将子组件自身的msg传过去
<template id="father">
        <div class="father">
            <p>这是父组件</p>
            <p>这是儿子跟他说的话 {{parentMsg}} </p>
            <hr>
            <son :tell-dad="change"></son>
        </div>
    </template>
    <template id="son">
        <div class="son">
            <p>这是子组件===》{{msg}}</p>
            <p><button @click="tellDad(msg)">告诉爸爸</button></p>
        </div>
    </template>
    <script>
    // 父组件可以将自己方法传递给子组件来调用,
    //实现子组件更改父组件的数据
    Vue.component("father",{
        template:"#father",
        data(){
            return {
                parentMsg:""
            }
        },
        methods:{
            change(msg){
                this.parentMsg = msg;
            }
        }
    })
    Vue.component("son",{
        template:"#son",
        props:["tellDad"],
        data(){
            return {
                msg:"今晚不学习了。。"
            }
        }
    })
    new Vue({
        el:"#app"
    })
</script>

2、每一个组件或者实例都会有自定义事件,和触发事件的能力,父组件给子组件绑定一个自定义事件,这个事件的处理程序却是父组件的一个方法,当子组件触发这个事件的时候,相当于父组件的方法被执行

  • 这里父组件通过@tell-dad=“change”给子组件绑定父组件自身的change方法。
  • vue中通过this.$emit触发自定义事件 (事件名,参数)
  • 点击子组件的按钮时,触发tell方法,而tell方法中通过$emit触发了父组件绑定在在子组件上的tell-dad方法,并且将msg数据当参数传递过去。调用了父节点的change方法。
<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div class="father">
            <p>这是父组件 ==> {{parentMsg}}</p>
            <hr>
            <son @tell-dad="change"></son>
        </div>
    </template>
    <template id="son">
        <div class="son">
            <p>这是子组件</p>
            <p><button @click="tell">btn</button></p>
            <p>{{msg}}</p>
        </div>
    </template>
</body>
<script src="./base/vue.js"></script>
<script>
    Vue.component("father",{
        template:"#father",
        data(){
            return {
                parentMsg:""
            }
        },
        methods:{
            change(msg){
                this.parentMsg = msg
            }
        }
    })
    Vue.component("son",{
        template:"#son",
        methods:{
            tell(){
                //触发绑定在自身的事件  tell-dad
                //vue中通过this.$emit触发自定义事件  (事件名,参数)
                this.$emit("tell-dad",this.msg)
                // this.tellDad(this.msg);
            }
        },
        data(){
            return {
                msg:"今天天气不错!"
            }
        }
    })
    new Vue({
        el: "#app"
    })
</script>
案例

国王组件中有数据国库,只能国王操作国库的数据,国王下的子民需要每次都上供自身一半的工资到国库中,但是子民不能直接操作国库的数据。

  • 国王将自身的addMoney方法 :_give=“addMoney” 传递给子民。子民通过props接收该方法 props:["_give"] 子民通过调用_give来上供。
<body>
    <div id="app">
        <king></king>
    </div>
    <template id="king">
        <div>
            <p>我是国王~~</p>
            <p>国库:{{gk}}</p>
            <p>下面是我的子民</p>
            <hr>
            <pi :_give="addMoney"></pi>
        </div>
    </template>
    <template id="pi">
        <div>
            <p>我是伟大国王的子民</p>
            <input type="number" v-model="money">
            <p><button @click="jg">进贡</button></p>
        </div>
    </template>
    <script src="/base/vue.js"></script>
    <script>
        Vue.component("king",{
            template:"#king",
            data(){
                return {
                    gk:0
                }
            },
            methods:{
                addMoney(money){
                    this.gk += money;//King自己更改gk的数据
                }
            }
        })
        Vue.component("pi",{
            template:"#pi",
            data(){
                return {
                    money:100
                }
            },
            methods:{
                jg(){
                    this.money /= 2;
                    this._give(this.money)
                }
            },
            props:["_give"]
        })
        new Vue({
            el:"#app"
        })
    </script>
</body>

子民有100交50
3、 组件之间不仅可以通过$root $parent $children 来获取对应关系的组件,父组件还可以主动的通过ref为子组件做标记,也可以给dom做标记,也会形成ref链,可也以交互

【注】多个子组件标记的是同一个键名,获取到的应该是一个数组

父组件给子组件做$ref标记
  • 父组件aaa 给子组件bbb标记ref=“b”
<template id="aaa">
        <div>
            <button ref='btn' @click="get">get</button>
            <hr>
            <bbb ref="b"></bbb>
        </div>
    </template>
    <template id="bbb">
        <div>
            <input type="text" v-model="msg">
        </div>
    </template>
  • 在父组件的get中通过$refs.b找到子组件b标记,修改b中的msg数据
<script>
    Vue.component("aaa",{
        template:"#aaa",
        methods:{
            get(){
                // this.$children[0].msg = "bbbb"; //关系链  viewmodel链实现的
                this.$refs.b.msg = "bbbbbb"  //ref链实现的
            }
        }
    })
    Vue.component("bbb",{
        template:"#bbb",
        data(){
            return {
                msg:""
            }
        }
    })
    new Vue({
        el:"#app"
    })
</script>

4、 兄弟组件之间的通讯也是通过viewmodel关系链 和 $ref关系链来实现

通过big-borther的hitLittle方法,修改little-borther的crying的数据

<body>
    <div id="app">
        <big-borther></big-borther>
        <little-borther ref="little"></little-borther>
    </div>
    <template id="big-borther">
        <div>
            <p>我是大哥哥</p>
            <button @click="hitLittel">打弟弟</button>
            <hr>
        </div>
    </template>
    <template id="little-borther">
        <div>
            <p>我是小弟弟</p>
            <p v-if="crying">我枯了…………</p>
        </div>
    </template>
    <script src="/base/vue.js"></script>
    <script>
        Vue.component("big-borther",{
            template:"#big-borther",
            methods:{
                hitLittel(){
                    // this.$refs.little.crying = true//通过refs标记来通讯
                    this.$parent.$children[1].crying=true//通过parent  children关系链
                }
            }
        })
        Vue.component("little-borther",{
            template:"#little-borther",
            data(){
                return {
                    crying:false
                }
            }
        })
        new Vue({
            el:"#app"
        })
    </script>
</body>

5、 eventbus事件总线

  • 1.创建一个空的Vue实例 eventbus 事件总线 绑定与触发事件的过程
    创建vue对象 var angle = new Vue()
  • 2.B组件绑定一个自定义事件,第二个参数为需要执行的处理函数
    angel.$on(“事件名”,this.cry)
  • 3.A组件要执行B组件的事件名就可以让B组件自己去执行cry的方法
    angle.$emit(“事件名”)
<body>
    <div id="app">
        <big-borther></big-borther>
        <little-borther></little-borther>
    </div>
    <template id="big-borther">
        <div>
            <p>我是大哥哥</p>
            <button @click="hitLittel">打弟弟</button>
            <hr>
        </div>
    </template>
    <template id="little-borther">
        <div>
            <p>我是弟弟</p>
            <p v-if="crying">我枯了…………</p>
        </div>
    </template>
    <script src="/base/vue.js"></script>
    <script>
        //1、创建一个公共实例
        var angel = new Vue();
        Vue.component("big-borther",{
            template:"#big-borther",
            methods:{
                //3、通过$emit触发$on绑定的事件函数little
                hitLittel(){
                    angel.$emit("little")
                }
            }
        })
        Vue.component("little-borther",{
            template:"#little-borther",
            data(){
                return {
                    crying:false
                }
            },
            methods:{
                cry(){
                    this.crying = true
                }
            },
            mounted(){
                //2、给angel通过$on绑定cry事件,叫做 little
                angel.$on("little",this.cry)
            }
        })
        new Vue({
            el:"#app"
        })
    </script>
</body>

《个人笔记》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值