Vue组件间通信 - 非常全面

父子组件通信

1. 使用props和$emit()

父组件 -> 子组件:父组件使用v-bind(冒号是简写)传参,子组件通过props接收
子组件 -> 父组件:子组件使用$emit()向外传递自定义事件,父组件通过v-on(@是简写)监听,可以使用$event接收参数,也可通过定义一个method接收参数

这应该是项目中最常用的方法,不多说了吧。

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		
		<!-- 可以使用$event接收参数 -->
		<the-child
		:message="message"
		@changeMessage="message = $event"
		></the-child>
		
		<!-- 也可以通过定义一个methods接收参数 -->
		<the-child
		:message="message"
		@changeMessage="handleMessage"
		></the-child>
	</div>
</template>

<script>
import TheChild from './TheChild.vue';

export default {
	components: {
		TheChild
	},
	data() {
		return {
			message: '您好,加菲猫'
		}
	},
	methods: {
		handleMessage(val) {
			this.message = val;
		}
	}
}
</script>

子组件代码如下:

<template>
	<div>
		<h1>这是子组件</h1>
		<div>{{ message }}</div>
		<button @click="handleClick">按钮</button>
	</div>
</template>

<script>
export default {
	props: ['message'],
	methods: {
		handleClick() {
			this.$emit('handleMessage', '您点击了按钮');
		}
	}
}
</script>

2. 使用回调函数

父组件 -> 子组件:父组件使用v-bind(冒号是简写)传参,子组件通过props接收
子组件 -> 父组件:父组件通过v-bind将修改参数的方法传入子组件,然后由子组件调用这个方法

个人感觉这个方法并没有实际用处,毕竟这里没有真的在传递参数,不过倒是提供了一个思路,可以通过子组件调用父组件中的方法

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		
		<!-- 这里子组件接受了两个参数 -->
		<the-child
		:message="message"
		:changeMessageFn="handleMessage"
		></the-child>
	</div>
</template>

<script>
import TheChild from './TheChild.vue';

export default {
	components: {
		TheChild
	},
	data() {
		return {
			message: '您好,加菲猫'
		}
	},
	methods: {
		// 这个方法作为props传入子组件
		handleMessage() {
			this.message = '您点击了按钮';
		}
	}
}
</script>

子组件代码如下:

<template>
	<div>
		<h1>这是子组件</h1>
		<div>{{ message }}</div>
		<button @click="changeMessageFn">按钮</button>
	</div>
</template>

<script>
export default {
	props: ['message', 'changeMessageFn']
}
</script>

3. 使用$parent()和$children()

父组件 -> 子组件:父组件通过$children[0],$children[1]去访问子组件实例
子组件 -> 父组件:子组件通过$parent去访问父组件实例

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		<button @cilck="handleChildNumber">按钮</button>
		<the-child></the-child>
	</div>
</template>

<script>
import TheChild from './TheChild.vue';

export default {
	components: {
		TheChild
	},
	data() {
		return {
			message: '您好,加菲猫'
		}
	},
	methods: {
		handleChildNumber() {
			// 因为一个父组件可能会有很多子组件,所以需要使用下标去访问
			this.$children[0].number = 50;
		}
	}
}
</script>

子组件代码如下:

<template>
	<div>
		<h1>这是子组件</h1>
		<div>{{ number }}</div>
		<div>{{ parentMessage }}</div>
	</div>
</template>

<script>
export default {
	data() {
		return {
			number: 10
		}
	},
	computed: {
		parentMessage() {
			return this.$parent.message;
		}
	}
}
</script>

4. 使用provide + inject

provide/inject 是 Vue 内置的无依赖的组件通信接口,允许一个祖先组件向其所有后代注入一个依赖,不论组件层次有多深,这和 React 中的 Context 特性相似。
provide/inject 主要为高阶插件、组件库提供用例,并不推荐直接应用于应用程序代码中

父组件 -> 子组件:父组件使用provide提供一个值,子组件使用inject拿到父组件的值
子组件 -> 父组件:应该可以用同样的方法,还没验证过

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		<the-child></the-child>
	</div>
</template>

<script>
import TheChild from './TheChild.vue';

export default {
	components: {
		TheChild
	},
	provide: {
		message: '您好,加菲猫'
	}
}
</script>

子组件代码如下:

<template>
	<div>
		<h1>这是子组件</h1>
		<div>{{ message}}</div>
	</div>
</template>

<script>
export default {
	inject: ['message'],
}
</script>

5. 使用$attrs + $listeners

父组件 -> 子组件:父组件中使用v-bind进行传参,可以传递多个参数,子组件通过$attrs接收父组件传过来的参数
子组件 -> 父组件:子组件中使用$listeners获取到父组件中定义的事件监听器,也就是v-on,并执行绑定的事件处理函数

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		<div>姓名:{{ name }}</div>
		<div>年龄:{{ age }}</div>
		<the-child
		:name="name"
		:age="age"
		@changeName="changeName"
		></the-child>
	</div>
</template>

<script>
import TheChild from './TheChild.vue';

export default {
	components: {
		TheChild
	},
	data() {
	 return {
	 	name: '加菲猫',
	 	age: '18'
	 }
	},
	methods: {
		changeName() {
			this.name = '还是加菲猫'
		}
	}
}
</script>

子组件代码如下:

<template>
	<div>
		<h1>这是子组件</h1>
		<button @click="$listeners.changeName">按钮</button>
		<div>姓名:{{ $attrs.name }}</div>
		<div>年龄:{{ $attrs.age}}</div>
		<!-- $attrs包括了父组件传过来的name和age,还可以继续传给下一级组件 -->
		<grand-child v-bind="$attrs"></grand-child>
	</div>
</template>

<script>
import GrandChild from './GrandChild.vue'

export default {
	components: {
		GrandChild
	}
}
</script>

6. 使用ref属性

父组件 -> 子组件:父组件使用ref将子组件注册起来,使用this.$refs获取到组件实例,进而访问子组件的属性和方法

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		<the-child ref="childComp"></the-child>
		<button @click="changeName">按钮</button>
	</div>
</template>

<script>
import TheChild from './TheChild.vue';

export default {
	methods: {
		changeName() {
			console.log('点击前', this.$refs.childComp.age);
			this.$refs.childComp.changeAge();
			console.log('点击后', this.$refs.childComp.age);
		}
	}
}
</script>

子组件代码如下:

<template>
	<div>
		<h1>这是子组件</h1>
		<div>年龄:{{ age }}</div>
	</div>
</template>

<script>
export default {
	data() {
		return {
			age: 20
		}
	},
	methods: {
		changeAge() {
			this.age = 50;
		}
	}
}
</script>

兄弟组件通信

1. 使用props + $emit()

子组件传递的参数需要先经过父组件,才能传到另一个子组件。

父组件代码如下:

<template>
	<div>
		<h1>这是父组件</h1>
		<div>name: {{ name }}</div>
		<the-child1 :name="name" @handleChange="handleChange"></the-child1>
		<the-child2 :name="name"></the-child2>
	</div>
</template>

<script>
import TheChild1 from './TheChild1.vue';
import TheChild2 from './TheChild2.vue';

export default {
	data() {
		return {
			name: '加菲猫'
		}
	},
	methods: {
		// 接收子组件1传递的参数并给data赋值
		handleChange(name) {
			this.name = name;
		}
	}
}

子组件1代码如下:

<template>
	<div>
		<h1>这是子组件1,参数从这里传到子组件2</h1>
		<div>name: {{ name }}</div>
		<button @click="handleChange"></button>
	</div>
</template>

<script>
export default {
	props: ['name'],
	methods: {
		// 向外传递事件和参数
		handleChange() {
			this.$emit('handleChange', '还是加菲猫');
		}
	}
}
</script>

子组件2代码如下:

<template>
	<div>
		<h1>这是子组件2,这里接收子组件1传递的参数</h1>
		<div>name: {{ name }}</div>
	</div>
</template>

<script>
export default {
	props: ['name']
}
</script>

2. 使用EventBus = new Vue()

这个方法不需要经过父组件,所以就不需要使用v-bind和props。EventBus实际上就是Vue实例。在项目根目录下的main.js文件,创建一个EventBus并向外导出。

import Vue from 'vue';
import App from './App';

export const eventBus = new Vue();

new Vue({
	render: h => h(App),
}).$mount('#app');

在子组件1中引入eventBus并$emit()一个事件。因为eventBus是vue实例,所以上面存在$emit()方法。

子组件1代码如下:

<template>
	<div>
		<h1>这是子组件1,参数从这里传到子组件2</h1>
		<div>name: {{ myName }}</div>
		<button @click="handleChange"></button>
	</div>
</template>

<script>
import { eventBus } from '../main'; // 需要先引入eventBus

export default {
	data() {
		return {
			myName = '加菲猫'
		}
	}
	methods: {
		// 向外传递事件和参数
		handleChange() {
			this.myName = '还是加肥猫';
			eventBus.$emit('handleChange', '还是加菲猫');
		}
	}
}
</script>

子组件2也引入eventBus并监听自定义事件,把监听到的值传给当前组件的data

子组件2代码如下:

<template>
	<div>
		<h1>这是子组件2,这里接收子组件1传递的参数</h1>
		<div>name: {{ myName }}</div>
	</div>
</template>

<script>
import { eventBus } from '../main'; // 需要先引入eventBus

export default {
	data() {
		return {
			myName = '加肥猫'
		}
	},
	created() {
		eventBus.$on('handleChange', (name) => {
			this.myName = name;
		})
	}
}
</script>

3. 使用Vuex = new Vuex.Store()

创建一个文件夹store,里面定义一个index.js,在里面创建一个Vuex.Store并将这个实例导出。

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
	state: {
		name: '加肥猫'
	},
	mutations: {
		changeName(state) {
			state.name = '还是加肥猫';
		}
	}
})

export default store;

在main.js中导入这个实例,并注入到根Vue实例中。

import Vue from 'vue';
import App from './App';
import store from './store';

new Vue({
	render: h => h(App),
	store
}).$mount('#app');

子组件中可以通过$store.state.name进行访问

子组件1代码如下

<template>
	<div>
		<h1>这是子组件1,参数从这里传到子组件2</h1>
		<div>name: {{ $store.state.name }}</div>
		<button @click="handleChange"></button>
	</div>
</template>

<script>
export default {
	methods: {
		// 执行名为changeName的mutation
		handleChange() {
			this.$store.commit('changeName');
		}
	}
}
</script>

子组件2代码如下

<template>
	<div>
		<h1>这是子组件2,这里接收子组件1传递的参数</h1>
		<div>name: {{ $store.state.name }}</div>
	</div>
</template>

<script>
export default {
	
}
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值