VUE学习-组件传值(九)

一、父子组件传值(props+$emit)

A)、父向子传值(props)

1、编写父组件基础代码
<template>
    <div class="parent">
    <h2>parent:  </h2>
    </div>
</template>

<script>
    export default {
    
    };
</script>

<style scoped lang='scss'>
    .parent{
        border: 1px solid red;
        padding: 10px;
    }
</style>

在views包下创建Parent.vue文件,并配置路由信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UOX9PgNr-1627287095545)(image/122.png)]

展示效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xc2CU1G1-1627287095547)(image/123.png)]

2、编写子组件基础代码
<template>
    <div class="son1">
        <h2>son1: </h2>
    </div>
</template>

<script>
    export default {
    
    };
</script>

<style>
    .son1{
        border: 1px solid green;
        padding: 10px;
        margin: 10px;
    }
</style>

在views包下创建son1.vue文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fhVZm8fA-1627287095548)(image/124.png)]

在parent.vue中引入并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wzS0zun-1627287095549)(image/125.png)]

展示效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9fQ9vnT6-1627287095550)(image/126.png)]

3、使用

在父组件的data中添加值,并通过:绑定属性名和值(:name=“nickname”)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNeq3V4B-1627287095550)(image/127.png)]

<template>
    <div class="parent">
        <h2>parent:  </h2>
        {{ nickname }}
        <Son1 :name="nickname"></Son1>
    </div>
</template>

<script>
    import Son1 from '@/views/Son1.vue'
    export default {
        components:{
            Son1
        },
        data() {
            return {
                nickname:'王晓斌'
            }
        },
    };
</script>

<style scoped lang='scss'>
    .parent{
        border: 1px solid red;
        padding: 10px;
    }
</style>

在子组件中,通过props接值,并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYUwqCQj-1627287095551)(image/128.png)]

展示效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZGY5SQ3C-1627287095551)(image/129.png)]

B)、子向父传值($emit)

在子组件son1.vue中,添加一个按钮,并定一个方法,并在方法中通过$emit自定义一个事件(abc),并将值“王涛”放入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1ybv02n-1627287095551)(image/130.png)]

<template>
    <div class="son1">
        <h2>son1: </h2>
        {{ name }}
        <button @click="updatename">修改</button>
    </div>
</template>

<script>
    export default {
        props:["name"],
        methods:{
            updatename(){
                //自定义一个事件abc
                this.$emit('abc', '王涛');
            }
        }
    };
</script>

<style>
    .son1{
        border: 1px solid green;
        padding: 10px;
        margin: 10px;
    }
</style>

在父组件parent.vue中,通过子组件中的自定义事件@abc,并绑定一个方法abc1111,将值获取并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0MY7Gdw8-1627287095552)(image/131.png)]

<template>
    <div class="parent">
        <h2>parent:  </h2>
        {{ nickname }}
        <Son1 :name="nickname" @abc="abc1111"></Son1>
    </div>
</template>

<script>
    import Son1 from '@/views/Son1.vue'
    export default {
        components:{
            Son1
        },
        data() {
            return {
                nickname:'王晓斌'
            }
        },
        methods: {
            abc1111(e){
                this.nickname = e;
            }
        },
    };
</script>

<style scoped lang='scss'>
    .parent{
        border: 1px solid red;
        padding: 10px;
    }
</style>

二、祖孙组件传值(provide+inject)

A)、祖向孙传值(provide)

1、编写孙组件基础代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1u3ZrGg-1627287095555)(image/132.png)]

在views包下创建gradeSon.vue文件

<template>
    <div class="graderSon">
        <h2>GrageSon: </h2>
    </div>
</template>

<script>
    export default {
    
    };
</script>

<style scoped lang='scss'>
    .graderSon{
        border: 1px solid green;
        margin: 10px;
        padding: 10px;    
    }
</style>

在Son1.vue组件中引入并使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rfn7yPCT-1627287095556)(image/133.png)]

<template>
    <div class="son1">
        <h2>son1: </h2>
        {{ name }}
        <button @click="updatename">修改</button>
        <GradeSon></GradeSon>
    </div>
</template>

<script>

    import GradeSon from '@/views/GradeSon.vue'

    export default {
        props:["name"],
        components:{
            GradeSon
        },
        methods:{
            updatename(){
                //自定义一个事件abc
                this.$emit('abc', '王涛');
            }
        }
    };
</script>

<style>
    .son1{
        border: 1px solid green;
        padding: 10px;
        margin: 10px;
    }
</style>

展示效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x5ax6D8g-1627287095556)(image/134.png)]

2、引出问题

在parent.vue中添加age属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WIUxZKQD-1627287095557)(image/135.png)]

<template>
    <div class="parent">
        <h2>parent:  </h2>
        <div>姓名:{{ nickname }}</div>
        <div>年龄:{{ age }}</div>
        <Son1 :name="nickname" @abc="abc1111"></Son1>
    </div>
</template>

<script>
    import Son1 from '@/views/Son1.vue'
    export default {
        components:{
            Son1
        },
        data() {
            return {
                nickname:'王晓斌',
                age:18
            }
        },
        methods: {
            abc1111(e){
                this.nickname = e;
            }
        },
    };
</script>

<style scoped lang='scss'>
    .parent{
        border: 1px solid red;
        padding: 10px;
    }
</style>

展示效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UCcFWa2o-1627287095557)(image/136.png)]

问题:想让parent中的age值,在GrageSon组件内展示

3、解决办法一

使用props,将age从Parent.vue传到Son1.vue,再传到GrageSon.vue中

但是此方法不利于维护,麻烦

4、解决办法二(provide+inject)

依赖注入:https://cn.vuejs.org/v2/guide/components-edge-cases.html#%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5

使用provide,在parent中再加入一个数据对象job(为了演示)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8XEmL9n0-1627287095557)(image/137.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zkUIEsGR-1627287095558)(image/138.png)]

具体办法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V9wE07KG-1627287095558)(image/139.png)]

<template>
    <div class="parent">
        <h2>parent:  </h2>
        <div>姓名:{{ nickname }}</div>
        <div>年龄:{{ age }}</div>
        <div>工作:{{ job.type }}</div>
        <Son1 :name="nickname" @abc="abc1111"></Son1>
    </div>
</template>

<script>
    import Son1 from '@/views/Son1.vue'
    export default {
        components:{
            Son1
        },
        data() {
            return {
                nickname:'王晓斌',
                age:18,
                job:{
                    type:'java开发工程师'
                }
            }
        },
        //provide方法里面,设置依赖数据
        provide:function(){
            return {
                job:this.job
            }
        },
        methods: {
            abc1111(e){
                this.nickname = e;
            }
        },
    };
</script>

<style scoped lang='scss'>
    .parent{
        border: 1px solid red;
        padding: 10px;
    }
</style>
在想使用job的子组件或者孙组件中使用inject

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wmbfwgIE-1627287095559)(image/140.png)]

展示效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9FigCv3-1627287095559)(image/141.png)]

同理在GardeSon中进行上述操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KPciwZ9F-1627287095559)(image/142.png)]

B)、孙修改值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GrB4wFmE-1627287095560)(image/143.png)]

因为job传过来的是job对象,相当于是传递过来job对象的地址,所以子组件修改后,所有的组件都会修改

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fqq2hXKt-1627287095560)(image/144.png)]

三、兄弟组件传值($bus中央事件总线)

1、编写Son2.vue文件

<template>
    <div class="son2">
        <h2>Son2: </h2>
    </div>
</template>

<script>
    export default {
    
    };
</script>

<style scoped lang='scss'>
    .son2{
        border: 1px solid orange;
        margin: 10px;
        padding: 10px;
    }
</style>

展示效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wwaWl6Ft-1627287095560)(image/145.png)]

2、编写Son1.vue文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sd5cBN3T-1627287095561)(image/146.png)]

<template>
    <div class="son1">
        <h2>son1: </h2>
        {{ name }}
        <button @click="updatename">修改</button>
        <div>工作:{{ job.type }}</div>
        <div>
            公司:{{ company.name }}
            <br>
            地址:{{ company.address }}
        </div>
        <GradeSon></GradeSon>
    </div>
</template>

<script>

    import GradeSon from '@/views/GradeSon.vue'

    export default {
        data() {
            return {
                company:{
                    name:"橡树软件",
                    address:"西安雁塔区"
                }
            };
        },
        props:["name"],
        components:{
            GradeSon
        },
        //注入父组件设施的依赖数据
        inject:['job'],
        methods:{
            updatename(){
                //自定义一个事件abc
                this.$emit('abc', '王涛');
            }
        }
    };
</script>

<style scoped lang='scss'>
    .son1{
        border: 1px solid green;
        padding: 10px;
        margin: 10px;
    }
</style>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EHyJSGT3-1627287095562)(image/147.png)]

3、问题

将company相关信息传给Son展示

4、解决办法一

先传给parent,再传给son2,但是此方法过于繁琐,若碰到grageSon向son2传值的情况会更加复杂

5、解决办法二

$on:https://cn.vuejs.org/v2/api/#vm-on

依然使用$emit将值传出,再使用$on监听$emit定义的事件,但是此时面临一个问题为:在不同的组件中(如:son1和son2)的this.$emit和this.$on中的this不一致(this指自己当前的组件对象),所以在son2中通过this.$on监听不到son1中通过this.$emit所定义的事件因此,我们需要给vue的原型对象提供一个公共的对象,来存储事件,习惯使用$bus来命名因为这个公共的$bus需要包含$on和$emit,而vue的实例中包含,所以如下:

在main.js中:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Th9ixYZ4-1627287095562)(image/148.png)]

//给vue的原型对象添加一个$bus属性,作为将来所有vue实例的中央事件总线
Vue.prototype.$bus = new Vue()

在son1.vue中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hjZmX9pG-1627287095562)(image/149.png)]

<template>
    <div class="son1">
        <h2>son1: </h2>
        {{ name }}
        <button @click="updatename">修改</button>
        <div>工作:{{ job.type }}</div>
        <div>
            公司:{{ company.name }}
            <br>
            地址:{{ company.address }}
        </div>
        <button @click="toSon2">传给son2</button>
        <GradeSon></GradeSon>
    </div>
</template>

<script>

    import GradeSon from '@/views/GradeSon.vue'

    export default {
        data() {
            return {
                company:{
                    name:"橡树软件",
                    address:"西安雁塔区"
                }
            };
        },
        props:["name"],
        components:{
            GradeSon
        },
        //注入父组件设施的依赖数据
        inject:['job'],
        methods:{
            updatename(){
                //自定义一个事件abc
                this.$emit('abc', '王涛');
            },
            toSon2(){
                this.$bus.$emit('toSon2',this.company)
            }
        }
    };
</script>

<style scoped lang='scss'>
    .son1{
        border: 1px solid green;
        padding: 10px;
        margin: 10px;
    }
</style>

在son2.vue中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rj3zuR9Y-1627287095562)(image/150.png)]

<template>
    <div class="son2">
        <h2>Son2: </h2>
        {{company}}
    </div>
</template>

<script>
    export default {
        data() {
            return {
                company:{},
            };
        },
        mounted() {
            this.$bus.$on('toSon2',(e)=>{
                console.log(e);
                this.company = e;
            })
        },
    };
</script>

<style scoped lang='scss'>
    .son2{
        border: 1px solid orange;
        margin: 10px;
        padding: 10px;
    }
</style>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Shal2Sx1-1627287095563)(image/151.png)]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值