天天看点

总结:VUE组件间的通信

总结:Vue组件间的通信

一、父子组件

1、父组件传值属性传参,子组件

props

接收

例:

父组件:

<div>
	<child val="val"></child>
</div>
           

子组件:

<script>
export default {
	props: {
		val: {
			type: String,
			default: ''
		}
	}
}
</script>
           

2、

$attrs

接收父组件传值,但没有在子组件props声明

例:

父组件:

<div>
	<child val="val"></child>
</div>
           

子组件:

<div>
	<div v-bind="$attrs" :val="$attrs.val"></div>
</div>
           

注意

v-bind="$attrs"

此种方式

$attrs

会以键值对的形式默认展开在当前节点,但是当前实例的根节点会继承

$attrs

展开的属性

解决:

export default {
	inheritAttrs: false
}
           

3、

$refs

父组件获取子组件实例从而修改子组件的数据

例:

父组件:

<div>
	<child ref="child"></child>
</div>
           
export default {
	mounted () {
		this.$refs.child.val = '111111111111'
	}
}
           

子组件:

export default {
	data() {
		return {
			val: '1'
		}
	}
}
           

4、

$children

父组件获取子组件实例从而修改子组件的数据

父组件:

<div>
	<child></child>
</div>
           
export default {
	mounted () {
		this.$children[0].val = '111111111111'
	}
}
           

子组件:

export default {
	data() {
		return {
			val: '1'
		}
	}
}
           

注意

:此种方式不推荐使用,因为父组件内可能会有很多子组件,并且子组件有可能是为异步组件,所以父组件内各个子组件实例的顺序即

index

下标并不一定是固定的,所以有可能会导致获取改变失败。

5、

$emit

子组件派发事件,父组件内的子组件监听事件(事件由派发者监听)

子组件:

<div>
	<button @click="clickBtn">点击派发事件</button>
</div>
           
export default {
	methods () {
		clickBtn () {
			this.$emit('myClick', '子组件内部点击触发')
		}
	}
}
           

父组件:

<div>
	<child @myClick="myClick"></child>
</div>
           
export default {
	methods () {
		myClick (val) {
			console.log(val) // 子组件内部点击触发
		}
	}
}
           

注意

: 常用此种方式进行子组件向父组件的通信

二、兄弟组件之间的通信

注意:兄弟组件间的通信通常会使用第三方传递,即兄弟组件共同的父辈或者祖辈来传递数据

父辈组件:$parent || $root

<div>
	<child1></child1>
	<child2></child2>
</div>
           

子组件1:子组件1点击触发通讯给子组件2

<div>
	<div @click="say2"></div>
</div>
           
export default {
	methods () {
		say2 () {
			this.$parent.$emit('receice1')
		}
	}
}
           

子组件2:子组件2内部监听子组件1触发的通信

export default {
	mounted () {
		this.$parent.$on('receive1', () => {
			console.log('我接收到了来自兄弟的通信')
		})
	}
}
           

三、祖先和后代间的通信(跨很多组件)

provide

inject

正常很少使用这种方式,组件开发的时候偶尔会用到

祖先节点:

export default {
	provide () {
		return {
			val: 111
		}
	}
}
           

后代节点:

export default {
	inject: [
		'val'
	]
}
           

注意:单向传递数据(由祖先-》后代)

四、任意两个组件间的通信

vuex

、事件总线

bus

1、

vuex

采用最多的一种方式,不做示例

2、事件总线

bus

抽离出

bus

bus.js
           
import Vue from 'vue'
const Bus = new Vue()
export default Bus
           

使用

bus

import Bus from './utils/bus'
Bus.$emit('busHandle')
Bus.$on('busHandle', () => {})
           

注意

:注册的总线事件要在组件销毁时卸载,否则会多次挂载,造成触发一次但多个响应的情况

export default {
	beforeDestroy () {
        this.bus.$off('busHandle')
    }
}
           

模拟

BUS

的实现

// bus.js
class Bus {
	constructor: {
		this.classback = {} // 用来存储所有的事件
	}
	$on (name, fn) { // name:事件名形参名,fn为事件回调函数
		this.callback[name] = this.callback[name] || [] // 当name第一次被监听,则创建一个名为name的数组,用来存储所有的该name的回调函数
		this.callback[name].push(fn)
	}
	$emit (name, args) { // name、args触发回调函数传递的参数
		if (this.callback[name]) {
			this.callback[name].forEach((cb) => {
				cb(args) // 触发当前name身上绑定的所有的回调函数
			})
		}
	}
}
export default Bus
           

使用:引入

bus

bus.$on

bus.$emit