Vue组件通信

1.1.1 父组件向子组件传值

  • 父组件发送的形式 是以属性的形式 绑定值 到子组件身上。

  • 然后子组件用属性props接收

  • 在props中使用驼峰形式,模板中需要使用短横线的形式 。字符串形式的模板中 没有这个限制。

代码演示:

<div id="app">
 <!-- 传值有两种方式,分别是静态传值,和动态传值 -->
        <!-- 静态传值,在父组件视图层上写死一个数据 -->
<menu-item title="xiaoyu"></menu-item>
<br><br>
  <!-- 动态传值,从父组件取数据,渲染到父组件自己的视图层,然后再将这个数据,传递给子组件 -->
<menu-item v-bind:title="ptitle" :content="pcontent" :subtitle="psubtitle">
<script src="./js/vue.js"></script>
 <script>
 //父组件向子组件传值
 //全局(子)组件
 Vue.component('menu-item',{
 props:['title','content','subtitle'],
 template:`#menu-item`,
 data(){
     return{
         msg:'我是子组件中的msg'
     }
 },
 mounted(){
     console.log(this.title)
 }
 
 })
 
 //根组件(父组件)
 var vm=new Vue({
     //模板选择器
     el:'#app',
     //数据中心
     data(){
         return{
             ptitle:'亿缕阳光丨以爱报答爱',
             pcontent:'善良的爱有千万种,最让人惊喜的便是以爱报答爱。',
             psubtitle:'善良的爱有千万种'
         }
     },
     methods:{
     
     }
 })
 
 </script>

预览:

1.1.2 props命名规则

  • 在props中使用驼峰形式,模板中需要使用短横线的形式

  • 字符串的模板中没有这个限制

代码演示:

 <div id="app">
       
        <menu-item :mmsg="pmsg" :mnum="pnum"  :marr="parr" :mobj="pobj" :mname="pobj.name" :mage="pobj.age"></menu-item>
        <br><br>
       
    </div>
    <template id="menu-item">
        <div>
            <h1>{{msg}}</h1>
            <hr>
            <h1>
                我接收到父组件的数据如下所示
            </h1>
            <h1>{{mmsg}}</h1>
            <h1>{{mnum}}</h1>
            <div>
                <ul>
                    <li v-for="item in marr">{{item}}</li>
                </ul>
            </div>
            <h1>{{mobj.name}}----{{mobj.age}}</h1>
            <h1>{{mname}}</h1>
            <h1>{{mage}}</h1>
        </div>
    </template>
<script src="./js/vue.js"></script>
    <script>
        //父组件向子组件传值
        //全局组件
        Vue.component('menu-item',{
             // 父组件向子组件传值-props属性值类型
            props:['mmsg','mnum','marr','mobj','mname','mage'],
            template:`#menu-item`,
            data(){
                return{
                    msg:'我是子组件中的msg'
                }
            },
            mounted(){
               
            }
        })
        //根组件(父组件)   
        var vm=new Vue({
            //模板选择器
            el:'#app',
            //数据中心
            data(){

                return{
                    pmsg:'xiaoyu',
                    pnum:100,
                    parr:['apple','orange','banana'],
                    pobj:{
                        name:'hx',
                        age:20
                    }

                }

            },
            methods:{
               

            }
        })
    </script>

预览:

1.1.3 props属性值类型

props属性上定义的变量,可以接收到的数据的数据类型可以是:

  • 字符串 String

  • 数值 Number

  • 布尔值 Boolean

  • 数组 Array

  • 对象 Object

props自定义属性,申明属性类型的写法:

代码演示:

 <div id="app">
       <menu-item :mage="age" :mtitle="title" :mlist="list"></menu-item>
    </div>
    <template id="menu-item">
      <div>
        <h1>
            {{mage}}
        </h1>
        <h1>
            {{mtitle}}
        </h1>
        <ul>
            <li v-for="item in mlist">
                {{item}}
            </li>
        </ul>
      </div>
    </template>

 

<script src="./js/vue.js"></script>
    <script>
        //父组件向子组件传值
        //全局组件
        Vue.component('menu-item',{
             // 父组件向子组件传值-props属性值类型
             //声明属性,同时告知父组件属性数据类型
            // props:{
            //     mage:Number,
            //     mtitle:String,
            //     mlist:Array,
            // },
            props:{
                mage:{type:Number},
                mtitle:{type:String},
                mlist:{type:Array},
            },
            template:`#menu-item`,
            data(){
                return{
                    msg:'我是子组件中的msg'
                }
            },
            mounted(){
               
            }
        })
        //根组件(父组件)   
        var vm=new Vue({
            //模板选择器
            el:'#app',
            //数据中心
            data(){

                return{
                   
                   title:'小余你好',
                   age:20,
                   list:[100,200,300,400,500]

                }

            },
            methods:{
               

            }
        })
    </script>

预览:

1.1.4 子组件向父组件传值

  • 子组件用$emit()触发事件   ---  @click='$emit("enlarge-text", 5)'  你只要 单击click按钮,这个$emit()事件处理函数就被触发调用执行了。

  • $emit('','')  第一个参数为 自定义的事件名称     第二个参数为需要传递的数据

  • 父组件用v-on 监听子组件的事件

代码演示:

<div id="app">
        <h1 :style="{'font-size':fontSize+'px'}">
            {{pmsg}}
        </h1>
       <menu-item @big="handle"></menu-item>
   
    </div>
    <template id="menu-item">
      <div>
        <h1>{{msg}}</h1>

       <button @click="$emit('big',5)">扩大父组件中字体大小</button>
      </div>
    </template>
<script src="./js/vue.js"></script>
    <script>
        //子组件向父组件传值
        //全局组件
        Vue.component('menu-item',{
   
            template:`#menu-item`,
            data(){
                return{
                    msg:'我是子组件中的msg'
                }
            },
            mounted(){
               
            }
        })
        //根组件(父组件)   
        var vm=new Vue({
            //模板选择器
            el:'#app',
            //数据中心
            data(){

                return{
                    pmsg:'小马过河',
                    fontSize:20
                }

            },
            methods:{
               handle(val){
                 console.log('子组件传递过来的值是:'+val);
                 this.fontSize=this.fontSize+val
               }

            }
        })
    </script>

预览:

注意:

在父子组件 通过 自定义事件 进行通信时,表示从子组件中传递出来的参数值。此时,$event的值就是5或者10(子组件传递过来的值),而不是前面的事件对象。

      methods:{
                handle(event){
                    //event从子组件中传递出来的参数值
                    console.log(event);
                    // //扩大字体大小
                    // this.fontSize = this.fontSize + event;
                }
            }

或者

 methods:{
                handle($event){
                    console.log($event);

                    // //扩大字体大小
                     this.fontSize = this.fontSize + $event;
                }
            }

1.1.5 兄弟之间的数据传递

兄弟组件之间的通信,我们又叫 非父子组件间通信 ,

                                     又叫 中央事件总线(非父子组件间通信)。

  • 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据  

    • 提供事件中心    var hub = new Vue()

  • 传递数据方,通过一个事件触发hub.$emit('自定义事件名',传递的数据)

  • 接收数据方,通过mounted(){} 钩子中  触发hub.$on()方法名

  • 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据

代码演示:

一个组件向另一个组件 传递数据 (单向传递数据)

<div id="app">
        <menu-list></menu-list>
        <menu-item></menu-item>
    </div>
    <template id="menu-list">
        <div>
            <h1>我是menu-list组件</h1>
            <button @click="handle">我要传递数据</button>
        </div>
    </template>
    <template id="menu-item">
        <div>
            <h1>我是menu-item组件</h1>
        </div>
    </template>
<script src="./js/vue.js"></script>
    <script>
        //中间组件
        let hub=new Vue();
          // 传递数据方,通过一个事件触发hub.$emit(自定义事件名,传递的数据)
        Vue.component('menu-list',{
            template:`#menu-list`,
            data(){
                return{
                   
                }
            },
            methods:{
                handle(){
                    hub.$emit('send',200)
                }
               
            }
        })
        // 接收数据方,通过mounted(){} 钩子中  触发hub.$on()方法名
        Vue.component('menu-item',{
            template:`#menu-item`,
            data(){
                return{
                    num:0
                }
            },
            mounted(){
                hub.$on('send',function(val){
                    console.log('接收到兄弟组件传递过来的值是:'+val);
                })
            }
        })
        //根组件
        var vm=new Vue({
            //模板选择器
            el:'#app',
            //数据中心
            data(){

                return{
                   
                }

            },
            methods:{
               

            }
        })
    </script>

预览:

一个组件向另一个组件 传递数据,另一个组件向这个组件传递数据(双向传递数据)

<div id="app">
        <!-- <div>父组件</div> -->
        <!-- 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据 -->
        <!-- <button @click="handle">销毁</button> -->
       

        <menu-list></menu-list>

        <menu-item></menu-item>
       
    </div>
    <script src="js/vue.js"></script>
    <script>
        // 兄弟组件之间数据传递
        // 中间组件
        let hub = new Vue();

        Vue.component('menu-list',{
            template:`
            <div>
                <h1>我是menu-list组件</h1>
                <p>我是menu-list组件中的num:{{num}}</p>
                <button @click="handle">发送</button>
                <br>
                <p>menu-list组件,接收到兄弟组件传递过来的数据是:<b style="color:blue;font-size:20px;">{{y}}</b></p>
            </div>
            `,
            data(){
                return {
                    num:10,
                    y:null
                }
            },
            // 生命周期钩子函数
            mounted(){
                // 监听事件
                hub.$on('send-menu-list',(val)=>{
                    console.log(val);
                    // 1. 把接收到的数据,赋值给我数据中心的y去使用
                    this.y = val;
                    // 2. 把接收到的数据,让它参与num的计算
                    this.num += val;
                })
            },
            methods:{
                handle(){
                    // 1.自己组件内部数据变化
                    this.num++;
                    // 2.把数据 20 传递 走,送给兄弟组件去使用
                    hub.$emit('send-menu-item',20);
                }
            }
        });
       
        Vue.component('menu-item',{
            template:`
            <div>
                <h1>我是menu-item组件</h1>
                <p>我是menu-item组件里的num:{{num}}</p>
                <button @click="handle">发送</button>
                <br>
                <p>menu-item组件,接收到兄弟组件传递过来的数据是:<b style="color:red;font-size:20px;">{{x}}</b></p>
            </div>
            `,
            data(){
                return {
                    num:0,
                    x:null
                }
            },
            // 生命周期钩子函数
            mounted(){
                // 监听事件
                hub.$on('send-menu-item',(val)=>{
                    console.log(val);

                    this.x = val;
                })
            },
            methods:{
                handle(){
                    // 触发兄弟组件的事件
                    // 把数据 10000 传递 走,送给兄弟组件去使用
                    this.num++;
                    hub.$emit('send-menu-list',10000);
                }
            }
        });

        // 根组件
        let vm = new Vue({
            el:'#app',
            data:{
   
            },
            methods:{
                handle(){
                    // // 销毁事件
                    // hub.$off('send-menu-item');
                    // hub.$off('send-menu-list');
                }
            }
        })
    </script>

预览:

总结:

(1)创建一个空实例(bus中央事件总线也可以叫中间组件)

         //在vue上挂载一个$bus作为中央处理组件Vue.prototype.$bus = new Vue()

(2)利用$emit $on的触发和监听事件实现非父子组件的通信

        //触发自定义事件传递数据this.$bus.$emit('自定义事件名','传递的数据')

(3)//监听自定义事件获取数据this.$bus.$on('自定义事件名',fn)

1.1.6 组件之间消息传递的常用方式

对于vue来说,组件之间的消息传递是非常重要的,下面是我对组件之间消息传递的常用方式的总结。

(1)props和$emit(常用)(2)中央事件总线(非父子组件间通信)

这两个 我们上面的课程,已经阐述过。大家都会使用了。

1.1.6.1 $parent和$children

接着,我们看下 $parent($root)和$children($refs和ref) 怎么进行 组件之间的消息传递(也就是我们说的 组件之间的通信)

组件是vue的核心,组件的通信是vue的核心的核心

$parent和$children  是用来描述 父子组件通信的。

通信:数据的“动态的实时的”传递

通信(访问)--- 一定是  能 拿到 对方的 东西(数据中心的数据,方法中心的方法,计算属性等等)

子组件 访问 父组件    

$parent 获取父组件实例

在子组件created()中直接使用 this.$parent

我们通过 this.$parent  可以 在子实例(子组件)中 拿到 父实例(父组件)里的任何东西!!!

$parent

获取父组件    

可以获取父元素对象,在子组件中修改 会 影响父组件  

(注意这里的)    

可以this.$parent链式调用取父组件之上的组件

<div id="app">
        <parent></parent>
    </div>
 <script src="js/vue.js"></script>
    <script>

        // 子组件
        let child = {
            template:`
            <div>
                <h1>我是child子组件</h1>
            </div>
            `,
            // 生命周期
            created(){
                // 子访父
                console.log(this.$parent)
                // 访问父组件中的数据中心data里的数据
                console.log(this.$parent.msg);
                // 访问父组件中的方法中心methods里的方法
                console.log(this.$parent.run());  
                // 访问父组件中计算属性computed里的计算属性
                console.log(this.$parent.total);
            },
            data(){
                return {

                }
            }
        }
        let parent = {
            template:`
            <div>
                <h1>我是parent父组件</h1>
                <child></child>
            </div>
            `,
            data(){
                return {
                 msg:'xiaoyu',
                 num:10 
                }
            },
            computed:{
                total(){
                    return this.num*this.num
                }
            },
            components:{
                child
            },
            methods:{
               run(){
                return "hx"
               }
            }
        }

        // 根组件
        let vm = new Vue({
            el:'#app',
            data:{
   
            },
            methods:{
               
            },
            components:{
                parent
            }
        })
    </script>

优化后:

 <div id="app">
        <div>
            <h1>我是parent父组件</h1>
           
        </div>
        <parent id="parent">
        <child id="child">
            <div>
                <h1>我是child子组件</h1>
            </div>
        </child>
        </parent>    

    </div>
 // 子组件
        let child = {
            template:`#child`,
            }
            
        let parent = {
            template:`#parent
           
            `,
            }

预览:

 

父组件 访问 子组件

$children ($children 的值是数组)

$children 获取"全部的"子组件

在父组件mounted()直接使用 this.$children

获取 当前组件的子组件,子组件会被放进数组[]里    

获取子组件的下标后,操作和$parent一样

例如:

子组件的数组

this.$children

特别注意:

父访子,一定要在dom挂载后,我们调用生命周期钩子函数mounted(){}

<div id="app">
        <parent></parent>
    </div>

 

<script src="js/vue.js"></script>
    <script>

        // 子组件
        let child = {
            template:`
            <div>
                <h1>我是child子组件</h1>
            </div>
            `,
            // 生命周期
            created(){

            },
            data(){
                return {
                    message:'我是子组件中的数据',
                    num:20
                }
            },
            computed:{
                count(){
                    return this.num + 100;
                }
            },
            methods:{
                move(){
                    return 'ok';
                }
            }
        }
        let parent = {
            template:`
            <div>
                <h1>我是parent父组件</h1>
                <child></child>
            </div>
            `,
            data(){
                return {

                }
            },
            // 生命周期
            mounted(){
                // 父访子
                console.log(this.$children);
                // 访问子组件中的数据中心data里的数据
                console.log(this.$children[0].message);
                console.log(this.$children[0].num);
                // 访问子组件中的方法中心methods里的方法
                console.log(this.$children[0].move());
                // 访问子组件中计算属性computed里的计算属性
                console.log(this.$children[0].count);
            },
            computed:{
 
            },
            components:{
                child
            },
            methods:{
   
            }
        }
        // 根组件
        let vm = new Vue({
            el:'#app',
            data:{
   
            },
            methods:{
               
            },
            components:{
                parent
            }
        })
    </script>

优化后:

 <div id="app">
        <div>
            <h1>我是parent父组件</h1>
        </div>

        <parent id="parent">
             
            <child id="child"> 
                <div>
                <h1>我是child子组件</h1>
            </div>
        </child>
        </parent>
    </div>
 // 子组件
        let child = {
            template:`#child
             
            `,
            }
          let parent = {
            template:`#parent
           
            `,
            }

预览:

 

1.1.6.2 ref和$refs

ref 和$refs  父组件 和 子组件 (需要结合在一起使用)

父组件 访问 子组件

$refs 获取指定的子组件(常用)

例如:

获取:this.$refs.xxx获取子组件实例

 <div id="app">
        <parent></parent>
    </div>
<script src="js/vue.js"></script>
    <script>
        //ref 和$refs 
        // 子组件
        let child = {
            template:`
            <div>
                <h1>我是child子组件</h1>
            </div>
            `,
            // 生命周期
            created(){

            },
            data(){
                return {
                    message:'我是子组件中的数据',
                    num:20
                }
            },
            computed:{
                count(){
                    return this.num + 100;
                }
            },
            methods:{
                move(){
                    return 'ok';
                }
            }
        }
        let parent = {
            template:`
            <div>
                <h1>我是parent父组件</h1>
                <child ref="c1"></child>
            </div>
            `,
            data(){
                return {

                }
            },
            // 生命周期
            mounted(){
                // 父访子
                // 父组件 使用 $refs 获取 子组件,在视图层 要结合ref 一起使用。
                // this.$refs.子组件名称 (视图层你定义的子组件的名字)
                console.log(this.$refs.c1);
                // 访问子组件中的数据中心data里的数据
                console.log(this.$refs.c1.message);
                console.log(this.$refs.c1.num);
               
                // 访问子组件中的方法中心methods里的方法
                console.log(this.$refs.c1.move());
               
                // 访问子组件中计算属性computed里的计算属性
                console.log(this.$refs.c1.count);
            },
            computed:{
 
            },
            components:{
                child
            },
            methods:{
   
            }
        }

        // 根组件
        let vm = new Vue({
            el:'#app',
            data:{
   
            },
            methods:{
               
            },
            components:{
                parent
            }
        })
    </script>

预览:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值