接上篇《14.Vue父子组件数据传递》
上一篇我们主要讲解了Vue中父组件如何将值、方法、实例传给子组件,本篇我们来讲解非父子组件如何进行数据和方法的传递。
本系列博文使用的Vue版本:2.6.11
在讲非父子组件如何进行数据和方法的传递之前,我们先来补充一下上一篇的一个点,就是父子组件之间如何进行主动的获取数据和方法,而不是传递给对方。
一、父子组件主动获取数据和方法
这里的样例还是在之前的工程上进行的演示。
1、父组件主动获取子组件的数据和方法
假设我们在HelloWorld.vue页面想要主动调取Header.vue子组件的数据和方法,我们只需要进行两步:
(1)调用子组件时定义一个ref
<v-header ref="header"></v-header>
这里的ref中的参数,其实就是主动获取了Header.vue子组件的一个实例对象。
(2)在父组件中通过“this.$refs.实例名.属性、方法名”的方式来调用子组件的数据或方法
例如:
this.$refs.header.属性;
this.$refs.header.方法;测试:
在HelloWorld.vue页面调用子组件时定义ref,然后编写一个按钮,测试是否能通过引用实例获取到子组件的数据和方法:
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="hello">
<v-header ref="header"></v-header>
<h1>{{ msg }}</h1>
<button @click="getChildData()">获取子组件的数据和方法</button>
</div>
</template>
<script>
import Header from './Header.vue';
export default {
name: 'HelloWorld',
data () {
return {
msg: '首页父组件'
}
},
methods:{
getChildData(){
console.log(this.$refs.header.msg);//获取子组件的值
this.$refs.header.headRun();//调用子组件的方法
}
},
components:{
'v-header':Header
}
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
h1{
color:red;
}
</style>
子组件中定义其msg以及headRun方法:
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="header">
<h1>{{ msg }}</h1>
<button @click="headRun()">执行自己的方法</button>
</div>
</template>
<script>
export default {
name: 'header',
data () {
return {
msg: '头部组件'
}
},
methods:{
headRun(){
alert("子组件的方法");
}
}
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
.header{
background-color: #000;
}
h1{
color:#fff;
}
</style>
测试结果:
证明可以通过“this.$refs”获取到子组件的数据和方法。
2、子组件中主动获取父组件的数据和方法
子组件被父组件引用后,可以直接通过“this.$parent.属性、方法名”的方式来调用父组件的数据或方法
例如:
this.$parent.属性;
this.$parent.方法;测试:
在Header.vue子组件中编写一个按钮,来通过上述方式主动获取父组件的属性和方法:
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="header">
<h1>{{ msg }}</h1>
<button @click="headRun()">执行自己的方法</button>
<button @click="getParentData()">获取父组件的数据和方法</button>
</div>
</template>
<script>
export default {
name: 'header',
data () {
return {
msg: '头部组件'
}
},
methods:{
headRun(){
alert("子组件的方法");
},
getParentData(){
console.log(this.$parent.msg);
this.$parent.run();
}
}
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
.header{
background-color: #000;
}
h1{
color:#fff;
}
</style>
然后在父组件HelloWorld.vue中添加一个自己的run方法:
methods:{
getChildData(){
console.log(this.$refs.header.msg);//获取子组件的值
this.$refs.header.headRun();//调用子组件的方法
},
run(){
alert("这里是父组件的方法");
}
},
效果:
证明子组件可以通过“this.$parent”获取到父组件的数据和方法。
二、非父子组件获取数据和方法
讲完了父子组件之间主动、非主动的获取和传递数据和方法的方式后,我们来了解一下非父子组件(兄弟组件)之间如何获取数据和方法。
我们观察一下,之前我们写的工程中,组件结构如下:
其中首页组件和新闻组件就不是非父子组件,是兄弟组件。兄弟组件之间的传值有两种方式:
1、通过上级组件来进行传值
兄弟组件一定是有相同的祖先的,只要找到两方都有关系的父组件,便可通过父组件来获取兄弟组件的数据。
例如首页组件需要获取新闻组件的msg,可以先获取父亲组件的实例,通过父亲组件的实例获取父亲引用的新闻组件的实例,进而获取到新文组件的msg:
this.$parent.$refs.news.msg
使用这种方法简单粗暴,但是如果两兄弟组件的父组件隔代过多,链路过长,调用起来十分复杂,就不推荐这种方式了。
2、通过根组件实例广播数据
我们可以创建公共js文件,其中声明一个vue根组件实例,非父子组件可以同时引用根组件的实例,然后在传递信息的一方,通过根组件实例的广播数据方法“$emit”,广播一个key,对应一个值或者方法,然后在接收数据的一方,通过根组件实例的接收广播方法“$on”,获取对方广播的值。
这里我们进行一下测试,首先我们在model文件夹下新建一个公共js,名为“vueEvent.js”,用于引入和实例化vue根组件,最后暴露出来:
代码:
import Vue from 'vue'
var vueEvent = new Vue();
export default vueEvent;
然后首页组件HelloWorld.vue中引用刚刚的实例“vueEvent”,然后定义一个按钮和方法“emitNews”,向新闻组件News.vue广播一个数据(其msg):
<template>
<!-- 所有的内容要被根节点包含起来 -->
<div class="hello">
<v-header ref="header"></v-header>
<h1>{{ msg }}</h1>
<button @click="getChildData()">获取子组件的数据和方法</button>
<button @click="emitNews()">给News组件广播数据</button>
</div>
</template>
<script>
import Header from './Header.vue';
import vueEvent from '../model/vueEvent.js';
export default {
name: 'HelloWorld',
data () {
return {
msg: '首页父组件'
}
},
methods:{
getChildData(){
console.log(this.$refs.header.msg);//获取子组件的值
this.$refs.header.headRun();//调用子组件的方法
},
run(){
alert("这里是父组件的方法");
},
emitNews(){
vueEvent.$emit('to-news',this.msg);
}
},
components:{
'v-header':Header
}
}
</script>
<!-- 添加 "scoped" 属性来限制里面css样式只能被该组件引用 -->
<style scoped>
h1{
color:red;
}
</style>
在新闻组件News.vue中,我们在组件挂载时(生命周期函数mounted),获取首页组件HelloWorld.vue广播的数据:
<template>
<div class="News">
<v-header :title="title"></v-header>
<h1>新闻组件</h1>
<ul>
<li>111111</li>
<li>222222</li>
<li>333333</li>
</ul>
</div>
</template>
<script>
import Header from './Header.vue';
import vueEvent from '../model/vueEvent.js';
export default {
name: 'News',
data () {
return {
title:'新闻头部'
}
},
components:{
'v-header':Header
},
mounted(){
vueEvent.$on('to-news',function(data){
console.log(data);
});
}
}
</script>
<style scoped>
</style>
效果:
可以看到兄弟组件广播的数据被接收方获取到了。
非父子组件传值总结:
1、新建一个js文件,引入和实例化vue,并暴露该实例;
2、在需要广播的组件中引入刚才定义的实例;
3、通过“vue实例名.$emit('名称','数据')”广播需要传递的数据;
4、在接收数据的地方通过“vue实例名.$on('名称',方法定义)”接收广播的数据,格式如下:
vue实例名.$on('名称',function(data){ });
参考:
《IT营:itying.com-2018年Vue2.x 5小时入门视频教程》
转载请注明出处:https://blog.csdn.net/acmman/article/details/109436798