[Vue] vue学习笔记(11): 任意组件之间的通信

前提

在vue中可以轻易实现父组件向子组件传递数据,但是子组件给父组件传递数据(输入框执行用户信息更改)或任意两个组件之间传递数据(兄弟组件互相传递消息)就不能简单地传递props,需要其他方法

组件的自定义事件

通过props可以将信息传递给子组件,那么当子组件需要向上传递信息的时候呢, 除了使用props传递函数类的方法,我们还可以用自定义事件

通过父组件给子组件绑定一个事件someEvent

// App.vue
<Student @someEvent='getStudentName' />

// methods
methods: {
	getStudentName(name, ...params){
		console.log("Data received by App: ", name, params)
	}
}

🍃name, ...params的写法是为了区分传入的参数,...params会返回一个列表 i.e. getSth('alice', 90, 10, 73) -> name = 'alice', params = [90, 10, 73]

触发组件实例里的自定义事件

<!--Student.vue - template-->
<button @click='doSomething'>Send Student's Name<button>
// Student.vue - methods
methods: {
	doSomething() {
	// func getStudentName(name, ...params) called
		this.$emit('someEvent', this.name, 90, 10, 77)
	}
}

原生事件

使用native标签,vue就可以识别组件上的原生DOM事件

<Student @someEvent='getStudentName' @click.native='showSomething'/>

全局事件总线 globalEventBus

全局事件总线类似于自定义事件,触发事件的对象变成了根组件Root,也就是vm实例对象本身

全局事件总线并不是对所有情况都是必需,通常自定义事件和props就可以解决问题,但在某些情况下会有用处,例如跨代传输数据,同代之间传递数据

案例说明:App与MyItem组件之间传输数据,但它们中间有一个MyList组件,数据必须通过它,即使MyList根本不需要这些;这种情况下就可以考虑使用全局事件总线

创建vm并绑定

// main.js
new Vue({...
	beforeCreate() {
		Vue.prototype.$bus = this
	}
})

绑定以及解绑事件对应的方法

// App.vue
// method definitions above 
mounted() {
	this.$bus.$on('checkTodo', this.checkTodo)
	this.$bus.$on('deleteTodo', this.deleteTodo)
}, 
beforeDestroy() {
	this.$bus.$off('checkTodo')
	this.$bus.$off('deleteTodo')
}

触发事件

// MyItem.vue
handleCheck(id) {
	this.$bus.$emit('checkTodo', id)
}

handleDelete(id) {
	if (confirm('Want to Remove?')) {
		this.$bus.$emit('deleteTodo', id)
	}
}

PS. handleCheck & handleDelete是触发事件函数, checkTodo & deleteTodo是事件逻辑函数, 用来实现功能 >>> 大概就是这个意思

消息订阅和发布

利用pubsub-js库实现,其原理和geb相似

// App.vue
import pubsub from 'pubsub-js'

// deleteTodo()
deleteTodo(_, id){...}

mounted() {
	this.pubId = pubsub.subscribe('deleteTodo', this.deleteTodo)
}
beforeDestroy() {
	pubsub.unsubscribe(this.pubId)
}

⬆️解释:App组件订阅了一个名为deleteTodo的消息/频道,并且这个消息绑定的回调函数deleteTodo会得到两个参数{msgName, data},使用下划线作为占位符,并等待其他组件在该频道下发布消息⬇️

// MyItem.vue
import pubsub from 'pubsub-js'

handleDelete(id) {
	if (confirm('Want to Remove?')) {
		pubsub.publish('deleteTodo', id)
	}
}
posted @ 2023-12-18 20:45  Akira300000  阅读(11)  评论(0编辑  收藏  举报