剑走偏锋之Vue 组件通信(一)—通过$parent和$children构建自己的通讯方式

2,337 阅读2分钟

在我平常的开发中,很多问题都是见招拆招,遇到了便去解决。长此以往,出现了一个大问题,就是会反复的碰到这个问题,而反复去解决,因为上次解决的方式不一定能记到。就像你看你几个月前的代码,都觉得:卧槽,谁的代码,这么烂。所以,最好的方式就是总结,不断总结。

Vue 的简便之处便在于组件,组件之间的复用让Vue项目维护起来十分简便。而其中组件之间的通信就是重中之重,不管哪一个项目都有组件之间的通信。而针对不同情况下的组件之间通信又各不相同,简直五花八门。像最基础的props@emit 父子组件通信,大型项目官方推荐的Vuex全局状态管理,小型项目试用的Bus通信等等,接下来我就总结出几种剑走偏锋的几种组件通信。

vue 官方api 这张图片就是Vue 官方api 中的,通过$parent$children就可以访问组件的实例,拿到实例代表什么?代表可以访问此组件的一切方法和data。虽然官方说节制的使用,但是我还是选择了无视。接下来就该思考下怎么去拿到指定组件的实例。

这应该是个通用的方法,原理就是通过不断遍历找到符合标准的组件实例,通过拿到的组件实例来拿到该实例的方法和data

要注意边界情况,如在#app上拿$parent得到的是new Vue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组。也要注意得到$parent$children的值不一样,$children 的值是数组,而$parent是个对象

/**
* @desc 寻找指定组件实例
* @params {String} type 向上查找还是向下查找
* @params {Object} context 当前上下文(一般指this,把this 传进来就可以了)
* @params {String} componentName 要寻找的指定的组件名
*/
function findComponents (type, context, componentName) {
	if (['$parent', '$children'].indexOf(type) < 0) return

	let currentComponent = context[type]
	if (type === '$parent') currentComponent = [currentComponent]
	let designatedCom = null

	if (currentComponent.length) {
		for(const com of currentComponent) {
			const name = com.$options.name

			if (name === componentName) {
				designatedCom = com
				break
			} else {
				designatedCom = findComponents(type, com, componentName)
				if (designatedCom) break
			}
		}
		return designatedCom
	}
 }

这个方法可以向上向下寻找跨组件的子,父组件的实例,拿到实例后就可以拿到相应的data和方法。

使用此方法需要注意几点
一、第一个参数必须是['$parent', '$children']中的一种,否则返回undefined


二、该方法必须在mounted生命周期中使用,不然代码中的currentComponent.length的值是0,(别问我为什么,我也不知道为什么)

然后就可以通过此方法得到你指定的组件实例,当然你可能会问,有Vuex等其他的通信方法,为什么要使用这个方法,或者说在什么情况下合适使用该方法。如果你自己写了一个自定义通用组件,现在你的组员想用这个组件,但是你把控制组件状态的值都写在了Vuex上了,这时候就麻烦了。这时候使用这个方法应该说比较好,不需要其他的外部依赖,即拿即用。 最后说一句,该方法出自iview源码中的寻找组件方法,我只是将其稍微改造了下,你可以点此链接查看iview源码。