vue组件间通信的几种方式

vue组件间的几种通信方式

方法一、props/$emit
1、父组件向子组件传值

父组件中通过v-bind绑定需要给子组件传递的值,子组件中通过props拿到父组件传递的值

//App.vue父组件
<template>
  <div id="app">
    <Child v-bind:username="username"/>//前者自定义名称便于子组件调用,后者要传递数据名
  </div>
</template>
<script>
import Child from "./components/Child"
export default {
  name: 'App',
  data(){
    return{
      username:'张三'
    }
  },
  components:{
    Child
  }
}
//child子组件
<template>
  <div class="hello">
    <span>{{username}}</span>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  props:{
    username:{           //这个就是父组件中子标签自定义名字
      type:String,
      default:'', //默认值
      required:true
    }
  }
}
</script>
2、子组件向父组件传值

子组件中通过$emit给父组件传值,第一个参数为绑定的方法,第二个参数为要传递的值;父组件通过v-on监听子组件传来的方法。

// 子组件
<template>
  <div>
    <button @click="pushDataToParent">子组件向父组件传值</button>
  </div>
</template>
<script>
export default {
  name: 'app-header',
  data() {
    return {
      title:"Vue.js Demo"
    }
  },
  methods:{
    pushDataToParent() {
      this.$emit("pushDataToParent","子向父组件传值");//自定义事件  传递值“子向父组件传值”
    }
  }
}
</script>
// 父组件
<template>
  <div id="app">
    <Child v-on:pushDataToParent="receiveChildData" />//与子组件titleChanged自定义事件保持一致
   // receiveChildData($event)接受传递过来的文字
    <h2>{{title}}</h2>
  </div>
</template>
<script>
import Child from "./components/child"
export default {
  name: 'App',
  data(){
    return{
      title:"传递的是一个值"
    }
  },
  methods:{
    receiveChildData(e){   //声明这个函数
      this.title = e;
    }
  },
  components:{
   Child
  }
}
</script>
方法二、$emit / $on

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。
具体实现方式:

var Event=new Vue();
Event.$emit(事件名,数据);//需要传值的组件使用该方法
Event.$on(事件名,data => {});//接收数据的组件使用的方法
// 组件A
<template>
 <div id="app">
   <button @click="emitData">传值</button>
 </div>
</template>
<script>
export default {
 name: 'App',
 data(){
   return{
     title:"传递的是一个值"
   }
 },
 methods:{
   emitData(e){   //声明这个函数
     Event.emit('pushData','传值')
   }
 }
}
</script>
// 组件B
<template>
 <div id="app">
   
 </div>
</template>
<script>
export default {
 name: 'App',
 data(){
   return{
     title:"传递的是一个值"
   }
 },
 mounted(){
   	Event.$on('pushData',data=>{
   		console.log(data)
   	})
   }
}
</script>
方法三、provide/ inject

父组件向其所有子组件注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。换句话说:父组件中通过provide来提供变量,然后在子组件中通过inject来注入变量。

provide / inject 解决了跨层级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态。
// A组件
export default {
  provide: {
    data: '我要给你传值了,请接好'
  }
}
// B组件
export default {
  inject: ['data'],
  mounted () {
    console.log(this.data);  // 我要给你传值了,请接好
  }
}

需要注意的是:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的----vue官方文档
所以,上面 A.组件 的 data如果改变了,B组件的 data是不会改变的,仍然是原来传过来的值。

那么,provide和inject如何才能实现数据响应式

答案是使用vue2.6版本最新API Vue.observable 优化响应式 provide

 provide() {
     this.user= Vue.observable({
       username: "zhangsan"
     });
     return {
       user: this.user
     };
   },
   methods: {
     changeUsername() {
      this.user.username = 'lisi'
     }
   }
<template functional>
	<div>
  		{{inject.user.username}}
	</div>
</template>
<script>
export default {
   inject: {
  	user: {
    	//函数式组件取值不一样
    	default: () => ({})
  	}
   }
};
</script>
方法四、$attrs

继承所有的父组件属性(除了prop传递的属性、class 和 style ),通常和inheritAttrs一起使用,inheritAttrs默认值true,继承所有的父组件属性(除props的特定绑定),如果你不希望组件的根元素继承特性,设置inheritAttrs: false,但是class属性会继承

//父组件
<template>
  <div class="hello">
    <span>最外层组件</span>
    <First :name="'张三'" :age="28" :sex="'男'" />
  </div>
</template>

<script>
import First from "./first";
export default {
  name: "HelloWorld",
  components: {
    First
  },
  data() {
    return {};
  }
};
</script>
<template>
  <div class="hello">
    <span>第一层组件</span>
    <Second v-bind="$attrs" />
  </div>
</template>

<script>
import Second from "./second";
export default {
  name: "First",
  components: {
    Second
  },
  props: {
    name: String
  },
  created() {
    console.log(this.$attrs); //{age:18,sex:'男'}
  }
};
</script>
<template>
  <div class="hello">
    <span>第二层子组件组件</span>
  </div>
</template>

<script>
export default {
  name: "Third",
  data() {
    return {};
  },
  props: {
    age: Number
  },
  created() {
    console.log(this.$attrs);//{sex:'男'}
  }
};
</script>
方法五、vuex

此处省略一万字。。。啊哈哈哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值