父组件给子组件传递数据,通过父组件的数据绑定到子组件的prop进行传递
父组件:
<template> <div> <h1>父组件</h1> <children :childrenProp="fatherData"></children> </div> </template> <script> import Children from './Children' export default{ name:'Father', components:{ Children }, data(){ return{ fatherData:'来自父组件' } } } </script> <style scoped> div { border: 1px solid #ccc; } </style>
子组件:
<template> <div> <h1>子组件</h1> {{childrenProp}} </div> </template> <script> export default{ name:'Children', props:{ childrenProp:String }, data(){ return{ childrenData:'子组件' } } } </script> <style scoped> div { border: 1px solid #ccc; margin: 10px; } </style>
结果:
子组件传值给父组件,通过子组件的$emit,"发射"一个"事件"并携带子组件的数据给父组件。
子组件:
<template> <div> <h1>子组件</h1> {{childrenProp}} </div> </template> <script> export default { name: "Children", data() { return { childrenData: "来自子组件" }; }, created() { /* this 表示当前的组件 CustomEvent是一个自定义的事件 这里子组件创建完了之后,向父组件“发射”了一个自定义的事件,并且同时传递了数据 */ this.$emit("CustomEvent", this.childrenData); } }; </script> <style scoped> div { border: 1px solid #ccc; margin: 10px; } </style>
父组件:
<template> <div> <h1>父组件</h1> <!-- 父组件对子组件的自定义事件进行监听,并且设置对应的事件处理程序 --> <children @CustomEvent="EventProcess"></children> <!-- 打印子组件传来的数据 --> {{dataFromChildren}} </div> </template> <script> import Children from "./Children"; export default { name: "Fat", components: { Children }, methods: { /* 子组件传递来数据通过父组件的事件处理程序处理 子组件数据传给父组件 */ EventProcess(dataFromChildren) { this.dataFromChildren = dataFromChildren; } }, data() { return { dataFromChildren: "" }; } }; </script> <style scoped> div { border: 1px solid #ccc; } </style>
结果:
另外一种就是兄弟组件之间的传递,一般的使用方法是结合子组件传递父组件,父组件传递子组件。或者使用eventBus方式(通过eventBus去发送和接收自定义事件并处理)
EventBus.js
import Vue from "vue"; export default new Vue();
兄弟组件一(发送数据的一方):
<template> <div> <h1>BroOne组件</h1> <p>{{BroOneData}}</p> </div> </template> <script> // 导入 EventBus 实际是一个Vue对象 import EventBus from "./EventBus.js"; export default { name: "BroOne", data() { return { BroOneData: "来自BroOne组件" }; }, mounted() { /* 子组件创建完了之后,触发(EventBus)实例事件 */ EventBus.$emit("CustomEvent", this.BroOneData); console.log(this.BroOneData); } }; </script> <style scoped> div { border: 1px solid #ccc; margin: 10px; } </style>
另外一个兄弟组件(接收数据的一方):
<template> <div> <h1>BroTwo组件</h1> <p>{{fromSblingsData}}</p> </div> </template> <script> // 导入 EventBus 实际是一个Vue对象 import EventBus from "./EventBus.js"; export default { name: "BroTwo", data() { return { fromSblingsData: "" }; }, created() { /* 另外一个兄弟组件,监听事件并处理 */ let _this = this; EventBus.$on("CustomEvent", function(fromSblingsData) { _this.fromSblingsData = fromSblingsData; }); } }; </script> <style scoped> div { border: 1px solid #ccc; margin: 10px; } </style>
结果:
第四种方式就是通过Vue生态的
vuex
,这里不做赘述,有点类似eventBus。
除了以上父子兄弟关系的组件还有一种是祖孙关系,祖孙关系的数据传递使用前面的eventBus也行,另外就是Vue 2.4+新增加的
$attrs
,在子组件上v-bind=$attrs
,可以将当前组件的属性,除了prop
传递和class
及style
之外的属性一并传给子组件。
Father.vue
<template> <div class="father"> <p>father.vue</p> <son :msg="msg" :sonProperOne="fromFatherOne" :sonProperTwo="fromFatherTwo" @notify="log" v-on="$listeners" ></son> </div> </template> <script> import Son from "./Son"; export default { name: "Father", data() { return { msg: "Father.vue", fromFatherOne: "fromFatherOne", fromFatherTwo: "fromFatherTwo" }; }, methods: { log() { console.log("son called"); } }, components: { Son }, created() { console.log("---------- father created ----------"); console.log("this.$attrs:"); console.log(this.$attrs); } }; </script> <style scoped> .father { border: 1px solid #ccc; margin: 10px; } </style>
Son.vue
<template> <div class="son"> <p>Son.vue</p> prop:{{msg}} <grand :msg="sonmsg" :grandProperOne="fromSonOne" :grandProperTwo="fromSonTwo" @notify="log" v-bind="$attrs" ></grand> this.$attrs:{{$attrs}} </div> </template> <script> import Grand from "./grand"; export default { name: "Son", inheritAttrs: true, data() { return { sonmsg: "Son.vue", fromSonOne: "fromSonOne", fromSonTwo: "fromSonTwo" }; }, props: { msg: String }, components: { Grand }, methods: { log() { console.log("grand called"); } }, created() { console.log("---------- Son created ----------"); console.log("this.$attrs:"); console.log(this.$attrs); this.$emit("notify"); // 告诉父组件要触发事件 } }; </script> <style scoped> .son { border: 1px solid #ccc; margin: 10px; } </style>
Grand.vue
<template> <div class="son"> <p>Grand.vue</p> prop:{{msg}} <grandson :msg="grandmsg" :grandSonProperOne="fromGrandOne" :grandSonProperTwo="fromGrandTwo" v-bind="$attrs" @notify="log" ></grandson> this.$attrs:{{$attrs}} </div> </template> <script> import grandson from "./grandson"; export default { name: "grand", inheritAttrs: true, data() { return { grandmsg: "Son.vue", fromGrandOne: "fromGrandOne", fromGrandTwo: "fromGrandTwo" }; }, props: { msg: String }, components: { grandson }, methods: { log() { console.log("grandson called"); } }, created() { console.log("---------- grand created ----------"); console.log('grandson 绑定 v-bind="$attrs"'); console.log("this.$attrs:"); console.log(this.$attrs); this.$emit("notify"); // 告诉父组件要触发事件 } }; </script> <style scoped> .son { border: 1px solid #ccc; margin: 10px; } </style>
Grandson.vue
<template> <div class="grandson" @click="log"> <p>grandson.vue</p> prop:{{msg}} <br /> this.$attrs:{{$attrs}} </div> </template> <script> export default { name: "grandson", inheritAttrs: true, data() { return {}; }, props: { msg: String }, methods: { log() { console.log("grandson clicked"); } }, created() { console.log("---------- grandsonson created ----------"); console.log("this.$attrs:"); console.log(this.$attrs); this.$emit("notify"); // 告诉父组件要触发事件 } }; </script> <style scoped> .grandson { border: 1px solid #ccc; margin: 10px; } </style>
结果: