Vue组件间传值(超全,跨代)父传子,子传父,爷传孙,孙传爷,保姆级讲解

前言

看了很多vue组件间传参的帖子,发现很多不完整,今天闲来无事总结一下vue组件间传值,此文涉及到:父传子,子传父,爷传孙,孙传爷的组件间传值,写的比较详细,同学们也别嫌我啰嗦,此文应该达到了保姆级别,看不明白你来打我。
本次用到的三个组件分别命名为:FatherSonGrandSon

准备工作

首先看下三个组件的代码:

1.父组件

<template>
    <div class="father">
        <h1>父组件</h1>
        <Son></Son>
    </div>
</template>

2.子组件

<template>
    <div class="son">
        <h1>子组件</h1>
        <GrandSon></GrandSon>
    </div>
</template>

3.孙组件

<template>
    <div class="grandson">
        <h1>孙组件</h1>
    </div>
</template>

为方便区分这里简单写了一下样式,渲染效果如图:
在这里插入图片描述

组件间传值

1.父传子

首先将父组件的中toSon的值在父组件内渲染。

<template>
    <div class="father">
        <h1>父组件</h1>
        <h1>{{toSon}}</h1>
        <Son></Son>
    </div>
</template>

<script>
    import Son from './Son.vue'
    export default {
        name: "Father",
        components:{ Son },
        data(){
            return{
                toSon:"这是父组件传给子组件的值!~"
            }
        }
    }
</script>

注意:这里还没有进行传参
在这里插入图片描述

众所周知:父传子是使用自定义属性传参,使用props接收数据。
我们在父组件中使用的子组件处定义自定义属性:son

<Son :son="toSon"></Son>

然后我们在子组件中接收数据,接收使用的son一定和前面的自定义属性:son对应。

props: {
            son:String
        },

也可以这样写:

        props:["son"],

第一种写法可以指定接收的数据类型或者默认值,第二种写法比较便捷,可以按数组的形式直接加逗号往后排。
然后我们在子组件中使用接收的数据。

<template>
    <div class="son">
        <h1>子组件</h1>
        <h1>{{son}}</h1>
        <GrandSon></GrandSon>
    </div>
</template>

然后父传子就完成了,如图所示:
在这里插入图片描述

2.子传父

首先将需要传给父组件的子组件的值在子组件内部渲染出来:

<template>
    <div class="son">
        <h1>子组件</h1>
        <h1>{{toFather}}</h1>
        <GrandSon></GrandSon>
    </div>
</template>

<script>
    import GrandSon from './GrandSon.vue'
    export default {
        name: "Son",
        components:{ GrandSon },
        data(){
            return{
                toFather:"这是子组件传给父组件的值!~"
            }
        }
    }
</script>

注意:这里还没有传参
在这里插入图片描述

子传父靠的是自定义事件,接收数据使用的是$emit
这里我们在h1上加一个点击事件,调用sendToFather的方法,后期用来触发我们的自定义事件。

<template>
    <div class="son">
        <h1>子组件</h1>
        <h1 @click="sendToFather">{{toFather}}</h1>
        <GrandSon></GrandSon>
    </div>
</template>

然后在methods里处理此方法:

methods:{
            sendToFather() {
                this.$emit("father",this.toFather)
            }
        }

father表示我们触发点击事件调用函数sendToFather后,会触发自定义事件fatherthis.toFather表示子组件中要传给父组件的值。
在子组件处理完毕后我们进入父组件,需要在父组件调用子组件的位置添加自定义事件father,然后函数getFromSon就可以接收传来的数据,为了更直观化,我们先放一个坑valueOfSon用来接收数据,父组件代码如下:

<template>
    <div class="father">
        <h1>父组件</h1>
        <h1>{{valueOfSon}}</h1>
        <Son @father="getFromSon"></Son>
    </div>
</template>

<script>
    import Son from './Son.vue'
    export default {
        name: "Father",
        components:{ Son },
        data(){
            return{
                valueOfSon:"子组件接收数据的坑~"
            }
        },
        methods:{
            getFromSon(val){
                this.valueOfSon=val
            }
        }
    }
</script>

未传值时,页面如图:
在这里插入图片描述

然后我们点击子组件中h1这是子组件传给父组件的值!~ ,触发sendToFather函数,然后触发自定义事件father,将toFather的值传走,父组件中的father事件触发,调用getFromSon函数,将接收的值传给valueOfSon,我们就会发现留的坑数据改变为这是子组件传给父组件的值!~,传值成功。
在这里插入图片描述

3.爷传孙

首先说明:既然你学会了父传子,那么爷传孙自然不是难事,你可以先父传子,再子传孙,一步一步传,这里不再赘述。
这里用到的方法是$attrs传参,比起上面的更简洁一些,首先我们还是来一个初始状态,先将父组件的参数在父组件自身展示一下:

<template>
    <div class="father">
        <h1>父组件</h1>
        <h1>{{toGrandSon}}</h1>
        <Son></Son>
    </div>
</template>

<script>
    import Son from './Son.vue'
    export default {
        name: "Father",
        components:{ Son },
        data(){
            return{
                toGrandSon:"父组件传给孙组件的值!~"
            }
        },
    }
</script>

注意:现在还未传参
在这里插入图片描述

首先我们需要先在父组件引用的子组件上使用自定义属性,将值先传给子组件,这里我们定义自定义属性:grandson

<template>
    <div class="father">
        <h1>父组件</h1>
        <h1>{{toGrandSon}}</h1>
        <Son :grandson="toGrandSon"></Son>
    </div>
</template>

然后重点来了:我们此时不需要使用props在子组件接收数据,而是直接在子组件引用的孙组件上面绑定v-bind="$attrs",在这里此段代码就像导管一样,直接将数据传给了孙组件。

<template>
    <div class="son">
        <h1>子组件</h1>
        <GrandSon v-bind="$attrs"></GrandSon>
    </div>
</template>

那么如果说它将数据导给了孙组件,那么我们此时就可以在孙组件内部使用props接收数据,然后我们将接收到的数据展示出来。

<template>
    <div class="grandson">
        <h1>孙组件</h1>
        <h1>{{ grandson }}</h1>s
    </div>
</template>

<script>
    export default {
        name: "GrandSon",
        props:{
            grandson:String
        }
    }
</script>

接收成功,效果如图:
在这里插入图片描述

4.孙传爷

与上同理:既然你学会了子传父,那么孙传爷也不是难事,你可以先子传父,再父传爷,一步一步传,这里不再赘述。
这里用到的方法是$listeners传参,比起上面的更简洁一些,首先我们还是来一个初始状态,先将孙组件的参数在孙组件自身展示一下:

<template>
    <div class="grandson">
        <h1>孙组件</h1>
        <h1>{{ toFather }}</h1>
    </div>
</template>

<script>
    export default {
        name: "GrandSon",
        data(){
            return{
                toFather:"孙组件传给父组件的值!~"
            }
        }
    }
</script>

在这里插入图片描述

这里给h1"孙组件传给父组件的值!~"添加一个点击事件来触发sendToFather函数来传参:

<template>
    <div class="grandson">
        <h1>孙组件</h1>
        <h1 @click="sendToFather">{{ toFather }}</h1>
    </div>
</template>

然后在methods中处理sendToFather函数:

methods:{
            sendToFather(){
                this.$emit("father",this.toFather)
            }
        }

这里触发的是自定义事件father,后面定义,传走的值是toFather:"孙组件传给父组件的值!~"
然后重点来了:我们此时不需要使用自定义事件"father"在子组件接收数据,而是直接在子组件引用的孙组件上面绑定v-on="$listeners",在这里此段代码就像导管一样,直接将数据传给了父组件。

<template>
    <div class="son">
        <h1>子组件</h1>
        <GrandSon v-on="$listeners"></GrandSon>
    </div>
</template>

子组件部分处理完毕,再来看父组件,这里先来个坑用来接收数据,然后定义之前提到的自定义事件father,使其调用getFromGrandSon函数,然后在函数getFromGrandSon中处理数据,父组件代码如下:

<template>
    <div class="father">
        <h1>父组件</h1>
        <h1>{{ valueOfGrandSon }}</h1>
        <Son @father="getFromGrandSon"></Son>
    </div>
</template>

<script>
    import Son from './Son.vue'
    export default {
        name: "Father",
        components:{ Son },
        data(){
            return{
                valueOfGrandSon:"接收孙组件传参的坑~"
            }
        },
        methods:{
            getFromGrandSon(val){
                this.valueOfGrandSon=val
            }
        }
    }
</script>

未传参时,如图所示:
在这里插入图片描述

此时点击子组件中的h1文字触发点击事件,执行sendToFather函数,然后触发自定义事件father,在子组件中$listeners起到导管作用,将事件传给父组件,然后父组件中的father事件被触发,执行getFromGrandSon函数,将传来的值赋给valueOfGrandSon
如图所示:
在这里插入图片描述

OK!~,大功告成,到这里父传子,子传父,爷传孙,孙传爷就结束了,下面进行一些小拓展,已经理解的同学可以跳过。

拓展

  • 只是自己的一点见解,如有错误欢迎指正。

1.自定义属性

  • 在vue中我们经常用到一些动态属性,如:class:id:src,:key等等,
    这些属性有一个共同的特性那就是:他们都是系统规定好的,有特定作用的,比如:class后面跟值,可以动态绑定该元素的class。
    此类属性,我统称为:系统自带的属性
  • 而有一些属性是我们自己来写的,如上文中的 :son:grandson,这些属性只有我们自己知道他们是用来干嘛的,你甚至可以写 :abc:qwerdf来自定义这些属性。
    此类属性,我统称为:自定义属性
  • 需要强调的是,使用父传子或者爷传孙的时候,一定要使用自定义属性,如果你使用了系统自带的属性来传参是万万行不通的。

2.自定义事件

  • 在vue中我们也经常用到一些事件,如 @click@dbclick@keyup@keydowm等等,
    这些事件有一个共同的特性那就是:他们都是系统规定好的,有特定作用的,比如@click,就规定你点击某个区域来触发后面执行的函数。
    此类事件,我统称为:系统自带的事件
  • 而有一些事件是我们自己来写的,如上文中的@father,这些事件只有我们自己知道他什么时候被触发,上文中触发机制都写在了点击事件里,你也可以有更多的选择,你甚至可以写 @abc@qwerdf来自定义这些事件。
    此类事件,我统称为:自定义事件
  • 需要强调的是,使用子传父或者孙传爷的时候,一定要使用自定义事件,如果你使用了系统自带的事件来传参也是万万行不通的。

3.$attrs

  • $attrs是在vue的2.40版本新增的。
  • 包含了父作用域中不作为prop被识别 (且获取) 的特性绑定 (classstyle 除外)。当一个组件没有声明任何prop 时,这里会包含所有父作用域的绑定 (class style 除外),并且可以通过v-bind="$attrs"传入内部组件——在创建高级别的组件时非常有用。
  • 简单讲就是包含了所以父组件在子组件上设置的属性(除了prop传递的属性、classstyle )。

4.$listeners

  • $listeners是在vue的2.40版本新增的。
  • 包含了父作用域中的 (不含 .native 修饰器的)v-on事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
  • 简单点讲它是一个对象,里面包含了作用在这个组件上所有的监听器(监听事件),可以通过 v-on="$listeners" 将事件监听指向这个组件内的子元素(包括内部的子组件)。

5. inheritAttrs

  • inheritAttrs是在vue的2.40版本新增的。
  • 类型: boolean
  • 默认值:true
  • 如果父组件给子组件传递数据,子组件不使用props接收,那么这些数据将作为子组件的HTML元素的特性,这些特性绑定在组件的HTML根元素上。
  • 如果不希望本组件的根元素继承父组件的attribute,同时父组件传过来的属性(没有被子组件的props接收的属性),也不希望显示在子组件的dom元素上可以使用inheritAttrs: false,但是在子组件里可以通过$attrs获取到没有使用的注册属性, inheritAttrs: false不会影响 style 和 class 的绑定。

如:我在父组件中绑定自定义属性:abc,接收数据msg:"666"

<Son :abc="msg"></Son>
data(){
    return{
         msg:"666"
     }
}

在子组件中不适用props接收,我们就会看到这样的情况:自定义属性被渲染在了子组件的div上。

<div class="son" abc="666">
     <h1>子组件</h1>
</div>

而如果我们添加了inheritAttrs: false,如下:

export default {
        name: "Son",
        inheritAttrs: false,
        components:{ GrandSon },
    }

则会渲染成以下,自定义的属性消失了。

<div class="son">
     <h1>子组件</h1>
</div>

注意:对inheritAttrs操作不影响我们对$attrs的使用。

结语

文章到这里就结束了,如果你在这里学到了一些东西,希望能给我一个点赞,评论和收藏,十分感谢你的支持,博客之路我会本着认真的态度一直写下去。加油 ♪(・ω・)ノ

Vue中,父组件向子组件传递数据是通过props来实现的。而子组件向父组件传递数据,则需要通过自定义事件来实现。 首先,在父组件中,通过props属性将数据传递给子组件。可以在子组件标签上使用v-bind指令来动态绑定父组件的数据,或者直接在子组件标签上写入固定的值。 例如,在父组件中定义一个名为message的prop,并将一个字符串传递给子组件: ```vue <template> <div> <child-component :message="parentMessage"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent' }; } }; </script> ``` 然后,在子组件中,可以通过props属性接收父组件传递过来的数据,并在模板中使用该数据。 ```vue <template> <div> <p>{{ message }}</p> <button @click="sendMessageToParent">Send Message to Parent</button> </div> </template> <script> export default { props: ['message'], methods: { sendMessageToParent() { this.$emit('custom-event', 'Message from child'); } } }; </script> ``` 在子组件中,可以使用`props`属性声明接收的属性名,然后在模板中直接使用即可。另外,如果需要向父组件发送数据,可以使用`$emit`方法触发一个自定义事件,并传递需要发送的数据。 最后,在父组件中,可以通过在子组件标签上监听自定义事件来接收子组件传递的数据。 ```vue <template> <div> <child-component :message="parentMessage" @custom-event="receiveMessageFromChild"></child-component> <p>Message received from child: {{ childMessage }}</p> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent', childMessage: '' }; }, methods: { receiveMessageFromChild(message) { this.childMessage = message; } } }; </script> ``` 这样,就完成了子组件向父组件传递数据的过程。当子组件中的按钮被点击时,将会触发`custom-event`事件,并将消息发送给父组件,父组件接收到消息后,将其保存在`childMessage`变量中,并在模板中进行展示。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

湫风洛夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值