欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue组件间通信的几种方式

程序员文章站 2022-05-15 18:38:18
...

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

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

相关标签: vue 组件传值