组件通信

组件通信:

值得强调一点的是 无论组件通信结果如何,Vue都是单向数据流(组件之间的数据通信)。

1.父子通信:

绑定的是简单数据:
1.父组件中定义数据,通过单向数据绑定的形式,将数据绑定在子组件上,属性是自定义属性

2.子组件通过配置项中的props接受数据,props可以是一个数组,数组中放的是自定义属性名称

3.那么这个自定义属性可以向data中的数据一样直接在子组件的模板中使用。

4.父组件中的数据一旦发生改变,子组件中的数据也会跟着改变

举个栗子:
<div id="app">
  <father></father>
</div>
<template id="father">
   <div class="father-box">
        <h3>父组件</h3>
        <son v-bind:money = "money"></son>
        <son :money = "money"></son>
   </div>
</template>
<template id="son">
    <div class="son-box">
        <h3>子组件</h3>
        <p> {{ money }} </p>
    </div>
</template>
<script>
   Vue.component('father', {
      template : "#father",
      data (){
        return {
          money : 100
        }
      }
   })
   Vue.component('son', {
       template : "#son",
       props : [money]
   })
   new Vue({
      el: "#app",
   })
</script>

子父通信:

效果上间接使用的父组件的东西。
绑定复杂数据类型:

1.父组件中的数据是一个复杂数据类型,那么父组件绑定数据的时候,给子组件一个地址。
2.子组件可以通过这个地址来修改这个数据。
3.在效果上,子组件和父组件建立了通信,违背了单向数据流。
多说无益:
 <div class="app">
		<father></father>
 </div>
 <template id="father">
    <div class="father-box">
      <p>父组件 {{ setmoney.money }}</p>
      <son v-bind:setmoney="setmoney"></son>
    </div>
 </template>
 <template id="son">
     <div class="son-box">
       <input type ="text" v-model = "setmoney.money"/>
       <p>子组件 {{ setmoney.money }}</p>
     </div>
 </template>
 <script>
   Vue.component('father', {
      template : '#father',
      data () {
          return {
            setmoney : {
               money : 100
            }
          }
      }
   })
   Vue.component('son', {
      template : '#son',
      props : [setmoney]
   })
   new Vue({
      el : '.app'
   })
 </script>
除了这种传递对象的方式,父组件还可以传递一个方法给子组件.
1.父组件定义方法,然后将这个方法通过单向数据绑定的形式传递给子组件
2.子组件通过props属性接受,然后通过@click="方法名"
举例:
<div class="app">
		<father></father>
</div>
<template id="father">
	   <div>
	   	<h3>father</h3>
	   	<p> {{ money }} </p>
	   	<son :getmoney="getmoney"></son>
	   </div>
</template>
<template id="son">
	   <div>
	   	<h3>son</h3>
	   	<button @click="getmoney(100)">添加</button>
	   </div>
</template>
<script>
    Vue.component('father', {
    	template : '#father',
    	data () {
    		return {
    			money : 0
    		}
    	},
    	methods : {
    		getmoney (value){
    			this.money += value
    		}
    	}
    })
    Vue.component('son', {
    	template : '#son',
    	props : ['getmoney']
    })
	new Vue ({
		el : '.app'
	})
</script>
同自定义事件来实现通信:
--父组件上定义数据 和方法
--在子组件上绑定自定义事件
--子组件定义方法,在这个方法中通过 this.$emit(eventtype,实际参数)来调用
自定义事件的处理程序
 <div id="app">
    <King></King>
 </div>
   <template id="king">
       <div>
         <h3> I am king </h3>
         <!-- <People v-on: get = "get"></People> -->
         <p> 国库中有:{{ gk }}</p>
         <People @get = "get"></People>
       </div>
   </template>
   <template id="people">
     <div>
       <h3> I am people </h3>
       <button @click = "give"> 交钱 </button>
     </div>
   </template>
<script>
Vue.component('King',{
       template: '#king',
       data () {
         return {
           gk: 0
         }
       },
       methods: {
         get( value ){
           this.gk += value 
         }
       }
     })
     Vue.component('people',{
       template: '#people',

       data () {
         return {
           money: 2000
         }
       },
       methods: {
         give () {
           this.$emit('get', this.money/2)
         }
       }
     })
     new Vue({
       el: '#app'
     })  
</script>

非父子通信:

1.ref:

使用ref来绑定组件(ref也可以绑定DOM元素)
---在父级的模板中,使用ref = refName绑定在两个兄弟组件上。
---在任意一个子组件中,就可以通过this.$parent.$refs.refName就可以获取另一个组件,
同时这个组件上的数据和方法都可以获取到。
<div id="app">
    <Father></Father>
</div>

<template id="father">
    <div>
      <h3> 我是父亲 </h3>
      <hr>
      <Boy ref = "boy" ></Boy>
      <hr>
      <Girl ref = "girl" ></Girl>

      <div ref = 'hello'>
        你好
      </div>
    </div>
 </template>

 <template id="boy">
      <div>

        <h3> I am boy </h3>
        <p> 我现在有:{{ cash }}</p>
      </div>
 </template>

<template id="girl">
    <div>
      <h3> I am girl </h3>
      <button @click = 'give'> 给body 1000</button>
    </div>
</template>
<script>
  Vue.component('Father',{
    template: '#father',
    data () {
      return {
        name: 'father'
      }
    }
  })
  Vue.component('Boy',{
    template: '#boy',
    data () {
      return {
        cash: 2000
      }
    },
    methods: {
      incrementCash (value) {
        this.cash += value
      }
    }
  })
  Vue.component('Girl',{
    template: '#girl',
    data () {
      return {
        money: 1000
      }
    },
    methods: {
      give(){
        // console.log('====================================');
        // console.log(this.$parent);
        // console.log('====================================');
        // console.log( this.$parent.$refs ) // { body: Vuecomponent,girl: VueComponent }
        this.$parent.$refs.boy.incrementCash( this.money )

        // this.$parent.$children
      }
    }
  })
  new Vue({
    el: '#app'
  })
</script>

2.通过事件总线bus

他是通过事件的发布(声明),以及事件的订阅(触发)来实行的。
首先创建一个bus对象:
 ---- var bus = new Vue()
 --在content组件中定义数据,和修改数据的方法
 --在content组件中通过created钩子,进行bus事件的发布
 ----created : {
       bus.$on('add', this.addcontent);
     }
--- 在MyButton组件的方法中通过bus进行事件的订阅
----iincrement() {
     bus.$emit( 'add' );
}
<div id="app">
    <my-button></my-button>
    <Count></Count>
 </div>
  <template id="button">
    <button @click = "increment"> increment </button>
  </template>
  <template id="count">
    <div>
      {{ count }}
    </div>
  </template>
  <script>
    var bus = new Vue()
    Vue.component('MyButton',{
    template: '#button',
    methods: {
      increment () {
        bus.$emit('add')
        }
      }
    })
     Vue.component('Count',{
    template: '#count',
    data () {
      return {
        count: 0
      }
    },
    methods: {
      addCount(){
        this.count ++
      }
    },
    created () { //created表示组件在创建结束之后就会自动触发的一个方法
      //表示组件的装载结束(template模板的装载)
     bus.$on('add',this.addCount)

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

组件生命周期:

钩子函数,就是options中的key,他的值是函数。
钩子函数写在其他函数的后面。
1.组件有哪几个阶段:
   初始阶段
   运行中阶段。
   销毁阶段

2.初始化阶段:

1.分为两个阶段:
   每个阶段包含两个生命周期钩子函数:
   钩子函数:
   1.beforeCreate:
     表示组件创建前的准备工作,为事件的发布订阅和生命周期做初始化。
     在这个钩子函数中:
        数据拿不到,真实DOM也拿不到。
     这个钩子函数在项目中没有什么实际用途。
   2.created :
     表示组件创建结束。
     这个钩子函数中:
       数据能够拿到,但真实DOM无拿到。
     这个钩子函数在项目中:
       数据请求,然后可以进行一次默认的数据修改。
   3.beforeMounte:
     表示组件装在前的准备操作
        判断el选项有没有,判断template有没有,如果没有需要手动装载。
        如果有,那么利用render函数进行模板的渲染。
     这个钩子函数中:
        数据拿到了,但真实DOM没有拿到。
     这个钩子函数在项目中:
        数据请求,可以进行一次数据的修改。
   4.mounted :
   表示组件装载结束,可以在视图中看到。
   这个钩子函数:
      数据能够拿到,真实DOM也能拿到。
   这个钩子函数在项目中:
      DOM操作可以进行,第三方库的实例化。
 总结:
 由上对比,我们可以知道,数据请求越提前越好,所以created常用于数据的请求和数据的修改,第三方库的实例化常在mounted中进行。

运行中阶段:

----运行中阶段一共有两个钩子函数:

beforeupdate
---表示数据更新前的准备工作。
---这个钩子不会主动执行,只有在数据更新的后,才会执行。
---这个钩子函数中:
 -----数据拿到了,并且拿到的是修改后的数据
 -----DOM也输出了
 --这个钩子函数更多的工作内容为:生成新的VDOM,然后通过diff算法进行两次VDOM对比。
 --这个钩子函数在项目中:
 -----因为他主要做的事情是内部进行的, 所以对我们而言没有太多的操作意义
 updated:
 --表示数据结束更新,通过render函数渲染真实DOM
 --这个钩子函数的执行也是, 当数据修改的时候才执行
 --这个钩子函数中
 ---数据拿到了, DOM也拿到了
 --这个钩子在项目中
 ---也是进行第三方库的实例化( DOM是改变的 )
 - 总结: 数据更新, 也要进行DOM操作那么, 我们使用update这个钩子

销毁阶段:

1.有两种销毁方式:

第一种:
用过开关销毁:
---这个组件真实DOM也会被删除掉

第二种:
通过调用vm.$destroy()
---这个组件的被删除了, 但是它的真实DOM的html结构还在
包含两个钩子函数
---beforeDestroy
---destroyed
---这两个钩子无差别
---这两个钩子在项目中
 ----做善后工作 , 手动清除一些计时器, 和一些方法, 还有第三方实例化出来的对象
 我们建议大家使用开关的形式来操作组件的销毁和创建
举例:
 <div id="app">
    <button @click = 'flag = !flag'> 销毁 </button>
    <life-circle v-if = "flag"></life-circle>
 </div>
<template id="life-circle">
    <div>
      <h3> 销毁阶段 </h3>
      <button @click = 'destroy'> 销毁 </button>
    </div>
</template>
<script>
  Vue.component('LifeCircle', {
      template : '#lifr-circle',
      methods : {
        destory () {
           this.$destory();
        }
      },
      created () {
        this.time = setInterVal(() =>{
            console.log(1)
        },1000)
      },
      beforeDestory () {
        console.log('beforeDestory');
      },
      destory () {
        console.log('destroyed');
        clearInterval( this.timer )
        document.querySelector('#app div').remove();
      }
  })
  new Vue({
    el: '#app',
    data: {
      flag: true
    }
  })
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值