Vue组件间通信方法总结
Vue组件通信是Vue开发者必须掌握的技能之一。本文将总结Vue中组件间通信的各种方法,包括父子组件、兄弟组件及祖先后代组件间通信。
父子组件通信
父子组件通信是Vue中最常见的通信方式。下面分别介绍组件间通信的几种方法。
Props
在Vue中父组件可以通过Props向子组件传递数据,子组件通过props选项接收父组件传递过来的数据,使得父子组件关系更加紧密。
<!-- 父组件模板 -->
<template>
<div>
<child :message="parentMsg"></child>
</div>
</template>
<!-- 父组件 -->
<script>
import Child from './Child.vue';
export default {
components: {
Child,
},
data() {
return {
parentMsg: 'hello',
}
},
}
</script>
<!-- 子组件 -->
<template>
<div>
<span>{{ message }}</span>
</div>
</template>
<script>
export default {
props: ['message'],
}
</script>
$emit/$on
子组件通过$emit触发一个自定义事件,父组件通过$on监听该自定义事件。
<!-- 父组件模板 -->
<template>
<div>
<child @my-event="eventHandler"></child>
</div>
</template>
<!-- 父组件 -->
<script>
import Child from './Child.vue';
export default {
components: {
Child,
},
methods: {
eventHandler(param) {
console.log(param);
},
},
}
</script>
<!-- 子组件 -->
<template>
<div>
<button @click="clickHandler"></button>
</div>
</template>
<script>
export default {
methods: {
clickHandler() {
this.$emit('my-event', 'Hello from child!');
},
},
}
</script>
$refs
Vue中的$refs可以让父组件直接访问子组件的DOM实例或者子组件实例,但是需要注意的是,$refs在子组件挂载之后才可以访问。
<!-- 父组件模板 -->
<template>
<div>
<child ref="child"></child>
</div>
</template>
<!-- 父组件 -->
<script>
import Child from './Child.vue';
export default {
components: {
Child,
},
mounted() {
console.log(this.$refs.child);
},
}
</script>
<!-- 子组件 -->
<template>
<div>
<span>hello from child</span>
</div>
</template>
<script>
export default {}
</script>
兄弟组件通信
在Vue中,兄弟组件不能直接相互通信,但是可以通过相同的父组件作为中转站来实现通信。
<!-- 父组件模板 -->
<template>
<div>
<child1 ref="child1"></child1>
<child2 ref="child2"></child2>
</div>
</template>
<!-- 父组件 -->
<script>
import Child1 from './Child1.vue';
import Child2 from './Child2.vue';
export default {
components: {
Child1,
Child2,
},
mounted() {
this.$refs.child1.$on('my-event', param => {
this.$refs.child2.receiveFromChild1(param);
});
}
}
</script>
<!-- 子组件 -->
<template>
<div>
<button @click="clickHandler"></button>
</div>
</template>
<script>
export default {
methods: {
clickHandler() {
this.$emit('my-event', 'Hello from child1!');
},
},
}
</script>
祖先后代组件通信
祖先后代组件通信可以有多种方式,比如可以通过Vue自带的$parent/$children属性直接访问父组件/子组件,或者通过事件派发机制在组件树上派发事件。
$parent/$children
在Vue中,每个组件实例都拥有$parent和$children这两个属性,可以用来访问组件树上的父子组件,但需要注意的是,$parent/$children只会追溯到静态父子关系模板。
<!-- 父组件模板 -->
<template>
<div>
<child></child>
</div>
</template>
<!-- 父组件 -->
<script>
import Child from './Child.vue';
export default {
components: {
Child,
},
methods: {
logChildMethod() {
console.log(this.$children[0].hello());
},
},
}
</script>
<!-- 子组件 -->
<template>
<div>
<span>hello from child</span>
</div>
</template>
<script>
export default {
methods: {
hello() {
return 'hello from child method';
},
},
}
</script>
$attrs/$listeners
在Vue2.4.0之后,可以通过$attrs和$listeners实现组件之间更加灵活的通信,$attrs可以让组件在保留原本的属性之外接收额外的父级属性。$listeners可以让子组件直接将父组件时接收到的事件同时向自己的子孙传递。
<!-- 父组件模板 -->
<template>
<div>
<child attr1="I am attr1" @click="clickHandler" />
</div>
</template>
<!-- 父组件 -->
<script>
import Child from './Child.vue';
export default {
components: {
Child,
},
methods: {
clickHandler() {
console.log('hello from parent event');
},
}
}
</script>
<!-- 子组件 -->
<template>
<div>
<grand-child v-bind="$attrs" v-on="$listeners" />
</div>
</template>
<script>
import GrandChild from './GrandChild.vue';
export default {
components: {
GrandChild,
},
}
</script>
<!-- 孙子组件 -->
<template>
<button @click="$emit('click')">button text</button>
</template>
以上就是Vue组件间通信方法总结(父子组件、兄弟组件及祖先后代组件间)的完整攻略。
示例说明
接下来,给出一个具体的例子。
场景描述: 在一个VUE项目中,有一个页面,页面由多个组件构成,其中有一个筛选组件A,用户选择筛选条件后,其他组件根据筛选条件来实时展现数据。
首先,我们定义A组件:
<template>
<div>
<div class="form-group">
<label>条件一</label>
<input v-model="form.condition1" type="text">
</div>
<div class="form-group">
<label>条件二</label>
<select v-model="form.condition2">
<option v-for="option in options2">{{ option.label }}</option>
</select>
</div>
<button @click="search">搜索</button>
</div>
</template>
<script>
export default {
data() {
return {
form: {
condition1: '',
condition2: '',
},
options2: [
{ value: '1', label: '选项1' },
{ value: '2', label: '选项2' },
{ value: '3', label: '选项3' },
{ value: '4', label: '选项4' },
],
}
},
methods: {
search() {
this.$emit('search', this.form);
},
},
}
</script>
接着,在父组件中注册A组件,并监听它的search事件,触发自定义v-loading事件,把选择的筛选条件传递给子组件:
<template>
<div>
<A @search="onSearch"></A>
<B :condition="condition" @v-loading="handleLoading"></B>
<C :condition="condition"></C>
</div>
</template>
<script>
import A from './components/A.vue';
import B from './components/B.vue';
import C from './components/C.vue';
export default {
components: {
A,
B,
C,
},
data() {
return {
condition: {},
}
},
methods: {
onSearch(condition) {
this.condition = condition;
this.$emit('v-loading', true);
},
handleLoading(loading) {
this.$emit('v-loading', loading);
},
},
}
</script>
在B组件中接收父组件传递进来的筛选条件,然后根据条件请求数据,获取到数据后,通过$emit方法传递给父组件。
<template>
<div>
<ul>
<li v-for="item in list">{{ item.text }}</li>
</ul>
</div>
</template>
<script>
export default {
props: {
condition: Object,
},
data() {
return {
list: [],
}
},
mounted() {
this.fetchData();
},
watch: {
condition() {
this.fetchData();
},
},
methods: {
fetchData() {
getData(this.condition).then(response => {
this.list = response.data;
this.$emit('v-loading', false);
});
},
},
}
</script>
在C组件中接收父组件传递进来的筛选条件,然后根据条件展现数据:
<template>
<div>
<ul>
<li v-for="item in list">{{ item.text }}</li>
</ul>
</div>
</template>
<script>
export default {
props: {
condition: Object,
},
data() {
return {
list: [],
}
},
mounted() {
this.fetchData();
},
watch: {
condition() {
this.fetchData();
},
},
methods: {
fetchData() {
getData(this.condition).then(response => {
this.list = response.data;
});
},
},
}
</script>
通过以上代码,我们就实现了页面的数据实时筛选功能。
通过以上实例,可以看出vue的组件通信机制非常强大,能够很方便的解决我们在组件开发过程中遇到的各种通信问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue组件间通信方法总结(父子组件、兄弟组件及祖先后代组件间) - Python技术站