组件数据传递
为了清楚地说明组件间传递关系,以思特奇大学为例:Sitech组件为Exam和Lesson组件地父组件,Exam和Lesson组件为兄弟组件。
一、 props传递
- 父组件向子组件传值
在父组件调用子组件时,为子组件添加属性参数,子组件通过
props进行接收,这是最简单方便的一种传值方式,实现如下图。
父组件代码:<button @click="getExamName">从父组件获取名字</button>
子组件代码:
<button @click="getExamName">从父组件获取名字</button>
props: ['nameReceived'],
methods: {
getExamName() {
console.log('从父组件收到的名字为', this.nameReceived);
},
},
效果展示:
- 子组件向父组件传值:
通过使用props传递函数的方式实现子组件向父组件传值,实现流程如下:
(1) 在父组件中调用子组件时,在子组件标签中绑定函数,代码如下
<Exam :getExamName="getExamName" />
methods: {
getExamName(examName) {
console.log('父组件收到的考试名称', examName);
},
},
(2) 在子组件props中定义与绑定值相同的变量,用来接收父组件传递过来的函数,将子组件的要传递值作为函数的入参,调用该函数后就将参数传递给父组件,代码如下:
<button @click="sendExamName">向父组件传递名字</button>
props: ['getExamName'],
methods: {
sendExamName() {
this.getExamName(this.examName);
},
},
实现效果图如下:
二、组件的自定义事件
区别于JS内置事件,供组件使用,用于子组件向父组件传递数据。自定义事件在使用时需要与组件进行绑定,不用的时候进行解绑。实现原理为:父组件为子组件绑定带参数的自定义事件,然后在子组件中进行触发事件,并对事件进行传值。实现步骤如下:
- 绑定:
(1)在父组件中使用
<Exam @customEvent="testMethod" />
methods: {
testMethod(examName) {
console.log('父组件通过自定义事件收到的考试名称', examName);
},
},
(2) 在子组件中触发事件
this.$emit('customEventName', 参数)
父组件另一种绑定形式:
<A ref='refName' />
mounted(){
this.$refs.refName.$on('customEvent', this.testMethod)
}
使用第二种方式虽然看起来比较复杂,但是灵活性很高,如可以实现延时绑定等操作。
实现效果如下:
解绑:
this.$off('customEventName')
组件也可以绑定原生DOM事件,需要用native修饰符。
注意:
使用第二种方式绑定自定义事件,但是将回调函数直接写在this.$refs.refName('customEventName',回调函数) 中时,必须使用箭头函数,放置this指向错误。
自定义事件与props传递函数的区别: 使用props须在子组件中定义对应的变量,但是使用自定义事件不需要使用props进行接收。
三、全局事件总线
借助一个所有组件都可以访问到的全局公共总线来定义事件,需要接收数据的组件进行监听然后触发自身回调函数来接收数据,可以实现任意组件间的通信。
- 定义全局事件总线:
new Vue({
render: (h) => h(App),
beforeCreate() {
Vue.prototype.$bus = this; // 安装全局事件总线
},
}).$mount('#app');
- 使用全局事件总线:
(1)接收数据:A组件想接收数据,需在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods: {
testMethod(ExamName) {
console.log('父组件全局事件总线接收到的数据', ExamName);
},
mounted() {
this.$bus.$on('customBus', this.testMethod);
},
(2) 提供数据:
sendExamName() {
this.$bus.$emit('customBus', this.examName);
},
},
实现效果图如下:
Exam组件发送数据,父亲组件和兄弟组件都能收到数据,组件之间的通信不用再纠结父子关系,非常方便。
- 最好在beforeDestroy钩子中,使用$off去解除当前组件所用到的事件。
beforeDestroy() {
this.$bus.$off("customBus");
}
四、消息订阅与发布
消息的订阅与发布实现步骤与全局事件总线很像,都是需要数据的组件进行监听,由发送数据组件进行事件触发或者发布。
- 安装pubsub:
npm i pubsub-js - 消息发布:
sendExamName() {
pubsub.publish('test', this.examName);
},
- 消息订阅:
mounted() {
pubsub.subscribe('test', this.test);
},
- 取消订阅:
beforeDestroy(){
pubsub.unsubscribe('订阅实例PID')
}
实现的效果与全局事件总线的基本一样, 推荐使用全局事件总线。