vue中组件之间的通讯小结

vue中组件通讯的方式多种多样,下面提几个比较常见的通讯方式(不一定全哈):

1、父组件向子组件通讯--props

        总结下来就是父组件通过自定义属性传递变量,子组件通过props属性接收自定义属性映射的变量,从而达到变量传递,注意:这个传值子组件只能接收和使用,不能修改,应为vue规定这种变量传递只能是单向的,也就是所谓的单向数据流,很多框架都是单向数据流;

// 父组件中,father.vue写部分代码,全写太长了
<template>
    <div class="father">
        <Child :father_value="father_value"></Child>
    </div>
</template>
<script>
    import Child from './child.vue'  // 假设是在同一目录下,主要是不想多写
    export default{
        data(){
            return {
                father_value:"我是父组件传递的值"
            }
        },
        components:{
            Child
        }
    }
</script>
<style>
   // 样式就不写了
</style>




// 子组件  child.vue
<template>
    <div class="child">
        <p>{{father_value}}</p>    //页面显示 “我是父组件传递的值”
    </div>
</template>
<script>
    export default{
        props:{
            father_value:{
                type:String,
                default:"父组件传值"
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>

2、子组件向父组件通讯--emit

        上面说到父向子通讯是单向数据流,子组件无法修改父组件传递的值,那子组件怎么向父组件通讯呢?vue提供了emit方法,主要是可以调用父组件暴露到子组件的方法,既然能调用方法,那就能传递参数,这样就可以通讯了,注意:变量的对应,父组件在子组件暴露的自定义属性方法名,要与子组件调用emit方法第一个参数对应上,还有父组件fatherFunc中调用子组件传递的变量中的属性也要对应;

<!-- 父组件中,father.vue写部分代码,全写太长了 -->
<template>
    <div class="father">
        <Child @fatherFunc="fatherFunc"></Child>
        <p>{{father_value}}</p>  <!--“我是子组件传递给父组件的值” -->
    </div>
</template>
<script>
    import Child from './child.vue'  // 假设是在同一目录下,主要是不想多写
    export default{
        data(){
            return {
                father_value:""
            }
        },
        components:{
            Child
        },
        methods:{
            fatherFunc(params){
                cosnole.log(params.value)    // “我是子组件传递给父组件的值”
                this.father_value = params.value
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>




<!-- 子组件  child.vue -->
<template>
    <div class="child">
        <button @click="handleClick">点击</button>
    </div>
</template>
<script>
    export default{
        name:'child',
        data(){
            return {
                child_value:"我是子组件传递给父组件的值"
            }
        },
        methods:{
            handleClick(){
                this.$emit('fatherFunc', {value:this.child_value})
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>

3、组件之间的通讯--eventBus

        核心就是对vue实例$on、$emit、$off三个方法的使用,实质就是将方法暴露到全局,以供全局调用从而达到通讯的目的;

// 在main.js中
Vue.prototype.$eventBus = new Vue()  //全局挂载vue实例为eventBus

//以两个同级组件为例
<!-- compA 组件A-->
<template>
    <div class="compA"></div>
</template>
<script>
    export default {
        name:'compA',
        data(){
            return {
                compA_value:"我是组件A"
            }
        },
        created(){
            this.$eventBus.$on('compAFunc', this.compAFunc)   //注册方法
        },
        methods:{
            compAFunc(params){
                console.log(params.value)   //  "我是组件B"
            }
        },
        beforeDestroy(){
            this.$eventBus.$off('compAFunc')    //销毁方法
        }
    }
</script>
<style></style>



<!-- compB 组件B-->
<template>
    <div class="compB">
        <button @click='handleClick'>点击</button>
    </div>
</template>
<script>
    export default {
        name:'compB',
        data(){
            return {
                compB_value:"我是组件B"
            }
        },
        methods:{
            handleClick(){
                this.$eventBus.$emit('compAFunc', {value:this.compB_value})
            }
        }
    }
</script>
<style></style>

4、依赖注入--provide/inject

        在这里就不说是父子组件了,因为provide/inject穿透力不止是父子组件,看下面代码中有father组件、child组件、grandson组件是嵌套关系,在顶层father组件中使用provide暴露了变量,使用方法如代码,在嵌套组件child组件和grandson组件中都能能过inject接收,在这只写了三层嵌套,如果组件有三十层嵌套,顶层通过provide暴露了,里边的29层都能通过inject接收,当这是打举个例子,应该没有组件会嵌套三十层;这就是依赖注入的使用方式;

<!-- 父组件中,father.vue写部分代码,全写太长了 -->
<template>
    <div class="father">
        <Child @fatherFunc="fatherFunc"></Child>
    </div>
</template>
<script>
    import Child from './child.vue'  // 假设是在同一目录下,主要是不想多写
    export default{
        data(){
            return {
                father_value:"我是父组件的值"
            }
        },
        provide(){
            return {
                father_value:father_value
            }
        },
        components:{
            Child
        }
    }
</script>
<style>
   // 样式就不写了
</style>




<!-- 子组件  child.vue -->
<template>
    <div class="child">
        <p>{{father_value}}</p>   // 我是父组件的值
        <Grandson></Grandson>
    </div>
</template>
<script>
    import Grandson from './grandson.vue'
    export default{
        name:'child',
        inject:['father_value'],
        components:{
            Grandson
        },
        data(){
            return {}
        }
    }
</script>
<style>
   // 样式就不写了
</style>



<!-- 孙子组件  grandson.vue -->
<template>
    <div class="grandson">
        <p>{{father_value}}</p>   // 我是父组件的值
    </div>
</template>
<script>
    export default{
        name:'grandson',
        inject:['father_value']
        data(){
            return {}
        }
    }
</script>
<style>
   // 样式就不写了
</style>

5、获取组件实例--refs

        通过ref给组件设标志,通过refs获取组件实例对象,可以用实例对象获取内部变量以及调用内部方法;这种方式比较直接暴力,所以这种方式一般不是用来组件通讯,感觉有点杀鸡用牛刀了,通讯方式有很多,没必要用这个,下面$parent获取父组件实例也是一样的

// 父组件中,father.vue写部分代码,全写太长了
<template>
    <div class="father">
        <Child ref="childRef"></Child>
        <button @click='handleClick'>点击</button>
    </div>
</template>
<script>
    import Child from './child.vue'  // 假设是在同一目录下,主要是不想多写
    export default{
        data(){
            return {
                father_value:"我是组件的值"
            }
        },
        components:{
            Child
        },
        methods:{
            handleClick(){
                let childInstance = this.$refs['childRef']
                console.log(childInstance.child_value)
                childInstance.childFunc(father_value);  // "我是父组件传递的值:我是组件的值"
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>




// 子组件  child.vue
<template>
    <div class="child">
        
    </div>
</template>
<script>
    export default{
        data(){
            return {
                child_value:"我是子组件的值"
            }
        },
        methods:{
            childFunc(value){
                console.log("我是父组件传递的值:"+value)
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>

6、获取父组件--$parent

        其实和上面ref获取实例差不多,vue内部将当前子组件的父组件通过$parent暴露出来了,在子组件中可以直接获取,通过组件实例可以获取父组件的变量以及调用方法,还是不建议使用这种方式来实现通讯;提一嘴,vue还暴露根组件的实例$root

// 父组件中,father.vue写部分代码,全写太长了
<template>
    <div class="father">
        <Child></Child>
    </div>
</template>
<script>
    import Child from './child.vue'  // 假设是在同一目录下,主要是不想多写
    export default{
        data(){
            return {
                father_value:"我是组件的值"
            }
        },
        components:{
            Child
        },
        methods:{
            fatherFunc(value){
                console.log("我是父组件的方法,我被调用,这传递的参数:" + value)   // 我是父组件的方法,我被调用,这传递的参数:我是子组件的值
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>




// 子组件  child.vue
<template>
    <div class="child">
        <button @click="handleClick">点击</button>
    </div>
</template>
<script>
    export default{
        data(){
            return {
                child_value:"我是子组件的值"
            }
        },
        methods:{
            handleClick(){
                console.log(this.$parent.father_value)  //我是组件的值
                this.$parent.fatherFunc(child_value)  
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>

7、作用域插槽--slot

        先说一下插槽,插槽是vue提供的内部定义的组件<slot></slot>,全局都可以使用,作用是增加自定义组件的灵活性,可以在自定义组件中进行占位,调用自定义组件时可以自定组件之间增加不同的template,插槽分为匿名插槽、具名插槽以及作用域插槽,在这就只说一下作用域插槽;子组件可以通过插槽向父组件传递状态,子组件会将slot上定义的属性全部都暴露在slot-scope定义的形参中;其实这种通讯方式比较少用

// 父组件中,father.vue写部分代码,全写太长了
<template>
    <div class="father">
        <Child>
            <template slot-scope="scope">
                {{scope.data.value}}  // 我是子组件的值
            </template>
        </Child>
    </div>
</template>
<script>
    import Child from './child.vue'  // 假设是在同一目录下,主要是不想多写
    export default{
        data(){
            return {
                father_value:"我是组件的值"
            }
        },
        components:{
            Child
        }
    }
</script>
<style>
   // 样式就不写了
</style>




// 子组件  child.vue
<template>
    <div class="child">
        <slot :data={value:child_value}></slot>
    </div>
</template>
<script>
    export default{
        data(){
            return {
                child_value:"我是子组件的值"
            }
        }
    }
</script>
<style>
   // 样式就不写了
</style>

8、状态管理--vuex

        这玩意要单独写一篇文章才能说清楚,vuex是vue官方指定建议使用的状态集中管理插件,状态管理不是vue框架独有,react、svelte、小程序等都有;就是项目体系太大,通过一般的通讯方式太过麻烦,所以就将这个全局都可能用到的变量进行集中管理,然后全局都可以使用,vuex主要就是干这个的,而且这些变量还具有响应式;后面我独立写一篇文档说明vuex的使用方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值