时隔一年多 vue 又增加了新的方法 所以又把此篇文章从新整理
2.2.0 新增 provide 和 inject (隔代传值)
2.4.0 新增 $attrs 和 $listeners (隔代传值)
已经 2022 年 vue 已经出了3.0版本,在组件传值方便也有了一些改动,最近有时间来做一些添加和修正
组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。那么组件间如何通信,也就成为了vue中重点知识了。这篇文章将会通过props、$ref和 $emit 这几个知识点,来讲解如何实现父子组件间通信。
方法1:props
/$emit
(父子传值)
1.父向子
通过 props 传递数据
parent.vue
<template><divclass="parent">
父亲:{{message}}<child:my-message="message"mm="123"></child>
// 注意传递参数时要用—代替驼峰命名,HTML不区分大小写
// 通过属性传递 可传递动态属性 也可以传递静态属性 可传递数字、布尔值、数组、对象等任何类型的值</div></template><script>import childfrom'../base/child'exportdefault{data(){// 组件的data必须是函数return{
message:'好好学习'}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
child.vue
<template><divclass="child">
儿子:{{myMessage}}+{{mm}}</div></template><script>exportdefault{
props:['myMessage','mm'],// 方式一// 方式二// props: {// myMessage: Array //指定传入的类型,如果类型不对,会警告// },// // 方式三// props: {// myMessage: {// type: Array,// default: [5,6,7] //指定默认的值// }// }}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
2.子向父
通过 $emit 向父组件派发事件,父组件调用获取子组件参数
parent.vue
<template><divclass="parent"><child@tell='know'></child>// ref 作用在组件上 指向的是组件的实例 实例上的方法都可以调用</div></template><script>import childfrom'../base/child'exportdefault{data(){// 组件的data必须是函数return{}},
methods:{know(msg){alert(msg);}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
VUE 2 写法
child.vue
<template><divclass="child"@click='childClick'></div></template><script>exportdefault{data(){return{
msg:'我是子组件传递过来的数据'}},
methods:{childClick(){this.$emit('tell',this.msg)// 向父组件派发事件,this.msg为向父组件传递的数据}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.child{width: 100px;height: 100px;background-color: blue;}</style>
VUE 3 写法
child.vue
<template><divclass="child"@click='childClick'></div></template><script>exportdefault{
emits:['tell'],// vue 3需要对可触发的事件进行注册data(){return{
msg:'我是子组件传递过来的数据'}},
methods:{childClick(){this.$emit('tell',this.msg)// 向父组件派发事件,this.msg为向父组件传递的数据}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.child{width: 100px;height: 100px;background-color: blue;}</style>
方法2:$refs
/$emit
(父子调用方法)
1.父向子
通过 $refs 获取子组件数据 调用子组件方法
parent.vue
<template><divclass="parent"><divclass="todo"@click='todo'></div><childref='child'></child>// ref 作用在组件上 指向的是组件的实例 实例上的方法都可以调用</div></template><script>import childfrom'../base/child'exportdefault{data(){// 组件的data必须是函数return{}},
methods:{todo(){
console.log(this.$refs.child.msg)this.$refs.child.do()}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.todo{width: 100px;height: 100px;background-color: red;}</style>
child.vue
<template><divclass="child"></div></template><script>exportdefault{data(){return{
msg:'我是子组件传递过来的数据'}},
methods:{do(){alert('我是子组件的方法')}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
2.子向父
通过 $emit 向父组件触发一个事件 子组件就可以调用父组件的方法
parent.vue
<template><divclass="parent"><child@tell='fatherMethod'></child>// 父组件中 在子组件上监听子组件派发的tell方法 然后调用函数 就能调用子组件的方法</div></template><script>import childfrom'../base/child'exportdefault{data(){// 组件的data必须是函数return{}},
methods:{fatherMethod(){alert('我是父组件的know方法');}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
child.vue
<template><divclass="child"@click='childClick'></div></template><script>exportdefault{data(){return{
msg:'我是子组件传递过来的数据'}},
methods:{childClick(){this.$emit('tell')// 向父组件派发事件}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.child{width: 100px;height: 100px;background-color: blue;}</style>
3.子向父
父组件把方法传入子组件中 在子组件里直接调用这个方法
parent.vue
<template><divclass="parent"><child:fatherMethod='fatherMethod'></child>// 父组件把方法传入子组件中,在子组件里直接调用这个方法</div></template><script>import childfrom'../base/child'exportdefault{
methods:{fatherMethod(){alert('我是父组件的know方法');}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
child.vue
<template><divclass="child"@click='childClick'></div></template><script>exportdefault{
props:{
fatherMethod:{
type: Function,default:null}},
methods:{childClick(){this.fatherMethod()}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.child{width: 100px;height: 100px;background-color: blue;}</style>
方法3:$children
/$parent
(父子传值、调方法)
1.父向子
通过 $children 获取子组件数据和调用子组件方法(VUE 3已经移除,用 $refs 代替)
parent.vue
<template><divclass="parent"@click='fatherMethod'><child></child></div></template><script>import childfrom'../base/child'exportdefault{
methods:{fatherMethod(){this.$children[0].childMethod()// $children获取的是子组件的数组 通过索引找到对应的子组件的实例
console.log(this.$children[0].msg)}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.parent{width: 100px;height: 100px;background-color: blue;}</style>
child.vue
<template><divclass="child"@click='childClick'></div></template><script>exportdefault{data(){return{
msg:'我是子组件传递过来的数据'}},
methods:{childMethod(){alert('我是子组件的方法')}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.child{width: 100px;height: 100px;background-color: blue;}</style>
2.子向父
通过 $parent 获取父组件数据和调用父组件方法
$root
和$parent
都能够实现访问父组件的属性和方法,两者的区别在于,如果存在多级子组件,通过parent 访问得到的是它最近一级的父组件,通过root 访问得到的是根父组件(App.vue) 所以存在组件嵌套的情况下 不要使用 $root
parent.vue
<template><divclass="parent"><child></child>// ref 作用在组件上 指向的是组件的实例 实例上的方法都可以调用</div></template><script>import childfrom'../base/child'exportdefault{data(){// 组件的data必须是函数return{
msg:'父组件数据测试'}},
methods:{fatherMethod(){alert('我是父组件的方法')}},
components:{
child}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped></style>
child.vue
<template><divclass="child"@click='childClick'></div></template><script>exportdefault{data(){return{
msg:'我是子组件传递过来的数据'}},
methods:{childClick(){this.$parent.fatherMethod()
console.log(this.$parent.msg)}}}</script><!-- Add "scoped" attribute to limit CSS to this component only --><stylescoped>.child{width: 100px;height: 100px;background-color: blue;}</style>
方法4:$emit
/$on
(父子 兄弟 跨级)(VUE3 不支持)
VUE 2
父子 兄弟 跨级
这种方法通过一个空的Vue 实例
作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案 vuex。
eventBus.js
import Vuefrom'vue';exportdefaultnewVue();
a.vue
<template><div>