我一直感觉搞懂父子组件互相调用方法和传值,你就会vue,用了这么久还不会,最近就需求需要刚刚学会了几种方法

目录:

  1. 方案一:通过ref直接调用子组件的方法;
  2. 方案二:$on和$emit调用子组件的方法;
  3. 方案三:父组件传递数据给子组件
  4. 方案四:子组件与父组件通信
  5. 方案五:非父子组件通信1
  6. 方案六:非父子组件通信2

方案一:通过ref直接调用子组件的方法;

父组件中

<template>
    <div>
        <Button @click="handleClick">点击调用子组件方法</Button>
        <Child ref="child"/>
    </div>
</template>  
<script>
import Child from './child';
export default {
    methods: {
        handleClick() {
              this.$refs.child.sing('111');
		// 如果有显示隐藏页面时候就使用nextTick
		/**
		this.$nextTick(() => {
        		this.$refs.basLocationChildRef.getLocationById(row.id)
      		})
		*/
        },
    },
}
</script>

子组件

<template>
  <div>我是子组件</div>
</template>
<script>
export default {
  methods: {
	// ret 是父组件带来的参数
    sing(ret) {
      console.log('我是子组件的方法'+ret);
    },
  },
};
</script>

方案二:$on和$emit调用子组件的方法;

首先我们要了解$on和$emit

vm.$on( event, callback ):监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。

vm.$emit( event, […args] ):触发当前实例上的事件。附加参数都会传给监听器回调。 父组件

<template>
    <div>
        <div @click="click">点击父组件</div>
        <child ref="child"></child>
    </div>
</template>

<script>
    import child from "./child";
    export default {
        methods: {
            click() {
                this.$refs.child.$emit('childMethod','发送给方法一的数据') // 方法1:触发监听事件
                this.$refs.child.callMethod() // 方法2:直接调用
            },
        },
        components: {
            child,
        }
    }
</script>

子组件

<template>
    <div>子组件</div>
</template>

<script>
    export default {
        mounted() {
            this.monitoring() // 注册监听事件
        },
        methods: {
            monitoring() { // 监听事件
                this.$on('childMethod', (res) => {
                    console.log('方法1:触发监听事件监听成功')
                    console.log(res)
                })
            },
            callMethod() {
                console.log('方法2:直接调用调用成功')
            },
        }
    }
</script>

方案三:父组件传递数据给子组件

父组件:

<parent>
    <child :child-msg="msg"></child>  //这里必须要用 - 代替驼峰
</parent>

data(){
    return {
        msg: [1,2,3]
    };
}

子组件通过props来接收数据:

方式1:

props: ['childMsg']

方式2:

props: {
    childMsg: Array //这样可以指定传入的类型,如果类型不对,会警告
}

方式3:

props: {
    childMsg: {
        type: Array,    //传入的类型
        default: [0,0,0] //这样可以指定默认的值
    }
}

方案四:子组件与父组件通信

子组件:

<template>
    <div @click="testClick"></div>
</template>
methods: {
    testClick() {
        this.$emit('test','123'); //$emit(even,value)even 是一个函数,value 是传给父组件的值      , 触发名为test方法, '123'为向父组件传递的数据
    }
}

父组件接收:

<div>
 //监听子组件触发的test事件,然后调用change方法
    <child @test="change" :msg="msg"></child> 
</div>
methods: {
    change(val) {
        this.msg = val;  // val: 123
    }
}

方案五:非父子组件通信1

如果2个组件不是父子组件那么如何通信呢?这时可以通过eventHub来实现通信. 所谓eventHub就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件. let Hub = new Vue(); //创建事件中心

组件1触发

<div @click="eve"></div>

methods: {
    eve() {
        Hub.$emit('change','hehe'); //Hub触发事件
    }
}

组件2接收:

<div></div>

created() {
    Hub.$on('change', () => { //Hub接收事件
        this.msg = 'hehe';
    });
}

方案六:非父子组件通信2

父组件

<template>
	<div>
		<div v-if="!userShow">
			父组件内容区
			<el-button @click="lookUserInfo(scope.row)">&nbsp;查看</el-button> 
		</div>
		<!-- 子组件 -->
		<user-manager  v-if="userShow"  @close="showUserInfo" ref="child"> </user-manager>	
	</div>
</template>
<script>
	//导入用户页面
	import userManager from '../userManager.vue';
	export default {
	 	name:'taskManager',
	 	components:{userManager},
	 	data() {
	 		return {			
				userShow:false,				
			}
		},
		methods: {
			//显示子组件,隐藏父组件
			lookUserInfo(row) {
				this.userShow = true;
				this.$refs.child.chlidMethods
			},
			//此方法,子组件会调用,调用返回父页面:隐藏子组件,显示父组件
			showUserInfo() {
				this.userShow = false;
			},
		}
	}	
</script>

子组件


<template>
	<div>
		<!-- 返回父页面按钮 -->
		<div>
            <el-button @click="goToParent"> &nbsp;&nbsp;返回</el-button>
        </div>
		<div class="white-bg margin auto">
			<el-table>
				数据表格展示区	
			</el-table>
		</div>
	</div>
</template>
<script>
	export default {
	 	name:'userManager',
	 	data() {
	 		return {	
			}
		},	
		methods: {
			goToParent() {
				//调父页面方法
			    this.$emit('close');
			}
			chlidMethods() {
				console.log("父组件调子组件方法了")
			}
		}
	}	
</script>