组件通信

组件通信

  1. 为什么要进行组件通信?
    组件可以说是一个具有独立功能的整体,但是当我们要将这些组件拼接在一起时,这些组件相互之间要建立联系
    ,这个联系我们就称之为通信
  2. 组件通信的方式有以下几种( 王者级 )
    1. 父子组件通信
      使用props来实现
    2. 子父组件通信
      自定义事件
    3. 非父子组件通信
      ref链
      bus事件总线
    4. 多组件状态共享( 多个组件共用同一个数据 ) 大知识点( vuex )
      vuex

app实例的手动挂载

  new Vue({
    
  }).$mount('#app')

使用props实现父子组件通信

  • props
  1. 在父组件中的模板中将数据用单项数据绑定的形式,绑定在子组件身上
    <Son :money = "money"/>
    
  2. 在子组件的配置项中可以使用一个props配置项来接收这个数据,接收时props的取值可以是一个数组
    Vue.component('Son',{
        template:'#son',
        props:['money']
    })
    
  3. 在子组件模板中,接收的属性可以向全局变量一样直接使用
    <p>父亲给了我{{money}}块钱</p>
    
  • 问题一:props接收的money和子组件上绑定的自定义属性money是不是同一个?
    个人认为,一般都是,自定义属性会和数据写成一致。
  • 问题二:自定义属性的书写
    money---》money
    mask-flag---》maskFlag
    
  • 问题三:为什么data要定义为一个函数?
    1. 组件是一个独立的个体,那么它应该拥有自己的数据,这个数据应该是独立的数据
    2. 也就是说这个数据应该有独立的作用域,也就是有一个独立的使用范围,这个范围就是在这个组件内
    3. js的最大特征是函数式编程,而函数恰好提供了独立作用域。
  • 问题四:为什么data要有返回值?返回值还是一个对象?
    1. 因为Vue是通过observer来观察data选项的,所以必须要有返回值
    2. 因为Vue要通过es5的Object.defineProperty属性对对象进行getter和setter设置
  • 代码如下
//实例中应用
<div id="app">
<Father><Father/>
</div>
//设置模板
<template id="father">
    <div>
        <h3>这里是父组件</h3>
        <hr>
        <Son :aa="money" :mask-flag="maskFlag"/>
    </div>
</template>
<template id="son">
    <div>
        <h3>这里是子组件</h3>
        <p>我爸给我了{{aa}}块钱</p>
        <p>{{maskFlag}}</p>
    </div>
</template>

//创建组件
Vue.component('Father',{
    template:'#father',
    data(){//为什么要将data定义为函数?
        return{
            money:200,
            maskFlag:1000000
        }
    }
})

Vue.component('Son',{
    template:'#son',
    props:['aa','maskFlag']
})

new Vue({

}).$mount('#app')//APP的手动挂载

子父组件通信

  • 自定义事件
  1. 自定义事件通过 o n 定 义 on定义 onemit触发
       var vm = new Vue({
       el: '#app'
       })
    
       // 自定义事件的定义( 发布 )
    
       // vm.$on(自定义事件的名称,自定义事件的事件处理程序)
    
       vm.$on( 'aa', function () {
       console.log( 'aa' )
       })
    
       //自定义事件的触发 ( 订阅 )
    
       // vm.$emit( 自定义事件的名称,自定义事件处理程序需要的参数1,参数2,参数3)
    
       vm.$emit( 'aa' )
    
  2. 通过绑定在组件身上定义,通过 $emit触发
    <Son @aa = “fn”/>
  • 子父通信流程
  1. 在父组件的模板中,通过事件绑定的形式,绑定一个自定义事件在子组件身上
<Son @aa = "fn"/>   //这边要注意:fn是要在父组件配置项methods中定义
  1. 在子组件的配置项methods中写一个事件处理程序,在事件处理程序中触发父组件绑定的自定义事件。
Vue.component('Son',{
  template:'#son',
  data(){
    return{
      hongbao:500
    }
  },
  methods:{
    giveFather(){
      //进行父组件给子组件的自定义事件触发
      this.$emit('give',this.hongbao)
    }
  }
})
  1. 将子组件定义的事件处理程序giveFather,绑定到子组件的按钮上
<template id="son">
 <div>
   <h3>这里是son组件</h3>
   <button @click="giveFather">give</button>
 </div>
</template>
  • 完整案例如下
<div id="app">
 <Father></Father>
</div>
//  父模板
 <template id="father">
  <div>
   <h3>这是是father组件</h3>
   <p>儿子给了我 {{money}}</p>
   <Son @give="getHongbao"></Son>
  </div>
 </template>
 <template id="son">
   <div>
     <button @click="giveFather">give</button>
     <h3>这里是son组件</h3>
   </div>
 </template>

 Vue.component('Father',{
   template:'#father',
   data(){
     return{
       money:0
     }
   },
   methods:{
     getHongbao(val){
       this.money=val
     }
   }
 })
 Vue.component('Son',{
   template:'#son',
   data(){
     return{
       hongbao:500
     }
   },
   methods:{
     giveFather(){
       this.$emit('give',this.hongbao)
     }
   }
 })

 new Vue({
   el:"#app"
 })

 //自定义事件的定义(发布)
 //vm 为Vue实例
 vm.$on(自定义事件的名称,自定义事件的事件处理程序)
 vm.$on('aa',function(){
   console.log('aa')
 }//自定义事件的触发(订阅)
 //vm.$emit(自定义事件的名称,自定义事件处理程序需要的参数)
 vm.$emit('aa').

非父子组件通信

ref链

  <div id="app">
    <Father></Father>
  </div>
  <template id="father">
    <!--组件中根元素必须要唯一-->
    <div>
      <h3>这里是father<h3/>
      <button @click="look">点击获取儿子的money</button>
      <p>father的 n:{{n}}</p>//这个n的逻辑在下面父组件创建中
      <hr>
      <Son ref="son"></Son>
      <Girl ref= "girl" :n = "n" ></Girl>
      <!-属性与数据的绑定v-bind--->
    <div/>
  </template>
  <template id="son">
    <div>
      <h3>这里是son<h3/>
    </div>
  </template>
  <template id="girl">
    <h3>这里是girl</h3>
    <button @click="out">输出girl的this中的属性</button>
  </template>
  <script>
  Vue.component('Father',{
    tempalte:'#father'data(){
      return{
        n:0
      }
    },
    methods:{
      look(){
        this.n=this.$refs.son.money
      }
    }
  })

  Vue.component('Son',{
    template:"#son",
    data(){
      return{
        money:1000
      }
    }
  })

  Vue.component('Girl',{
    template:"#girl",
    data(){
      return{
        num:0
      }
    },
    methods:{
      out(){
        console.log(this)
        console.log(this.$attrs)
      }
    }
  })

  new Vue({
    el:'#app'
  })
  </script>

bus事件总线

  • bus事件总线,我们是通过 o n 来 定 义 事 件 , 通 过 on来定义事件,通过 onemit来触发事件
  • 案例:如下
  • 流程:
  1. 在其中一个组件的挂载钩子函数上做事件的声明
Vue.component('Sma',{
  template:'#small',
  data(){
    return{
      flag:false
    }
  },
  mounted(){//当前组件挂载结束,我们看到真实dom
  //mounted这个钩子函数的触发条件是组件创建时会自动触发
  //事件的声明
  var _this = this
  bus.$on('aa',function(){
    _this.flag= true
    console.log(this)//这个this值得是bus,我们需要的this应该是Sma这个组件,用_this保存this的指向
  })
  }
})
  1. 在另一个组件中,通过bus.$emit(‘aa’)来触发这个自定义事件
  • 完整案例
<div id="app">
  <Bro></Bro>
  <Sma></Sma>
</div>
<template id="big">
  <div>
    <h3>brother</h3>
    <button @click="hick">zou didi</button>
  </div>
</template>
<template id="small">
  <div>
    <h3>small bro</h3>
    <p v-show="flag">55555555555555</p>
  </div>
</template>

<script>
var bus= new Vue()//bus原型上有$on $emit

Vue.component('Bro',{
  template:'#big',
  methods:{
    hick(){
      bus.$emit('aa')
    }
  }
})

Vue.component('Sma',{
  template:'#small',
  data(){
    return{
      flag:true
    }
  },
  mounted(){
    //当前组件挂载结束,也就是我们在页面中可以看到真实dom
    //mounted这个钩子函数触发条件是创建时会自动触发
    //事件的声明
    var _this= this
    bus.$on('aa',function(){
      _this.flag=true
      console.log(this)//这个this指向的是bus,我们要的是Sma这个组件
    })
  }
})

new Vue({
  
}).$mount('#app')
</script>

非常规通信1

  • 业务:进行子父组件通信
  • 理解:使用自定义事件实现
  • 实现:父组件将一个方法通过属性绑定的形式给了子组件,子组件先是通过props接收这个方法,再执行这个方法
  • 这个方法不推荐大家使用
  • MVVM框架是单向数据流,但是上面的方法违背了单向数据流
  • 案例如下
<div id="app">
  <Father></Father>
</div>
//template
<template id="father">
  <div>
    <h3>father zujian</h3>
    <p>this is father n:{{n}}</p>
    <Son :add = "add"></Son>
  </div>
</template>

<template id="son">
  <div>
    <h3>son zujian</h3>
    <button @click="add(money)">give</button>
  </div>
</template>

<script>
  Vue.component('Father',{
    template:'#father',
    data(){
      return{
        n:0
      }
    },
    methods:{
      add(val){
        this.n= val
      }
    }
  })
  Vue.component('Son',{
    template:'#son',
    data(){
      return{
        money:1000
      }
    },
    props:['add']
  })
  new Vue({
    el:'#app'
  })
</script>

非常规2

  • 父组件传递一个对象类型给子组件
  • 子组件通过props接收
  • 子组件修改这个数据的时候,父组件也随之改变了?
  • 因为父组件给子组件传递的是对象的引用地址
  • 这种方法我们不推荐使用,违背了单项数据刘
  • 案例
<div id="app">
  <Father></Father>
</div>
//template
<template id="father">
  <div>
    <h3>this is father zujian</h3>
    <p>father:xioajinku:{{xiaojinku.money}}  </p>
    <Son :xiaojinku="xiaojinku"></Son>
  </div>
</template>

<template id="son">
  <div>
    <h3>this is son zujian</h3>
    <button>give</button>
    <input type="text" v-model="xiaojinku.money">
    <p> son xiaojinku:{{xiaojinku.money}}</p>
  </div>
</template>

<script>
  Vue.component('Father',{
    template:'#father',
    data(){
      return{
        xiaojinku:{
          money:1000
        }
      }
    }
  })
  Vue.component('Son',{
    template:'#son',
    props:['xiaojinku']
  })
  new Vue({
    el:'#app'
  })
</script>

this is son zujian
give

son xiaojinku:{{xiaojinku.money}}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值