vue组件间的传值(父子、子父、兄弟、后代、非兄弟)

目录

父向子传值

 子向父传值

兄弟传值

后代传值

非兄弟传值


在解决组件通讯方面,比较好用的就是vuex,但是在小型的项目中使用vuex就会有点大材小用的感觉,而且会增加文件体积。以下的都是不用vuex的传值解决方法,本文着重点是 后代的传值 和 非兄弟的传值,一些基本的操作就粗略带过。。。

好的,进入正题

现在假设 App.vue 下有两个子组件

brother.vuesister.vue

brother.vue 中有 brotherChild.vue

父向子传值

父子传值一般在子组件上绑定自定义的属性,然后子组件在实例中通过props接收该属性

app.vue:

brother.vue: 

export default {
    name:'brother',
    props:['name'],
    data () {
        return {
           
        };
    }
}

 子向父传值

这种情况一般使用emit反向传值,通过注册自定义事件,在事件函数中接收值

brother.vue:

export default {
    name:'brother',
    data () {
        return {
           
        };
    },
    aaa(){
        //注册自定义事件,并传递参数
        this.$emit('custom-event','你好,我是子组件传过来的值')
    }
}

 app.vue:

export default {
    name:'app',
    data () {
        return {
           
        };
    },
    bbb(params){
        //自定义事件的回调函数中  会接受一个参数  来自于注册事件时传递的参数
        console.log(params)  //输出结果:你好,我是子组件传过来的值
    }
}

兄弟传值

解决的方案基于上面的两种方法来实现的,操作的步骤:

1.brother.vue 自定义事件 传值

2.app.vue 绑定自定义事件 回调函数接收值

3.再将该值通过属性绑定传递到sister.vue

总结一下:子传给父,父再传给子

这种方法的话有个不太美观的问题就是,需要在app.vue中创建一个变量来存放第二步接收到的值

后代传值

咳咳,敲黑板,重点来了。这里要介绍的是 provide(提供) 和 inject (注入)两个属性,说实话这两个属性有点vuex的味道,在一些特殊情况下是非常滴好用的。这两个属性我只做大概的介绍,详细的大家可以百度,里面讲的很详细。

provide:相当于分享自己实例中的一些东西出去

inject用来接受provide分享出去的东西

假设一个场景:

brotherChild.vue 想要拿到 app.vue 的一些属性,用之前的方法的话,

需要绑定属性到brother.vue上,

brother.vue 接收属性再绑定到 brotherChild.vue上,

这时候brotherChild.vue又要通过props拿到。

可能层级比较少的时候不会觉得很麻烦,但如果是很多级的后代,需要重复的绑定接收,这简直就是折磨。。

此时 provide 和 inject 就起到的关键的作用,有了这个东西简直就像看到天使

app.vue:

export default {
    name:'app',
    provide(){
        return {
            //将当前的app.vue的实例分享出去
            'app':this
        }
    },
    data () {
        return {
          
        };
    },
}

app.vue 的N个后代组件:

export default {
    name:'appChild',
    inject:['app'],
    data () {
        return {
           
        };
    },
    methods:{
        fn(){
            // 获取到app.vue的整个实例  想要什么拿就完事了
            // 比如app上有个属性name,  this.app.name 就能拿到
            console.log(this.app)
        }
    }
}

看完是不是超简单,这个属性好用的地方就在于,父组件 provide 出去的东西,只要下面的后代组件 inject 一下就能拿到,无视距离(哭了,来自于爸爸无私的爱)

非兄弟传值

又假设一个场景:

brotherChild.vue 想拿 sister.vue 的一些属性(provide 和 inject 只能解决父组件和后代组件的问题,在这里已经无效了)

额。。想了想,这貌似有点棘手

不慌,办法总是有的,

这种情况我们可以使用 vue 实例中的 emit(触发自定义事件)和 on(监听自定义事件)

首先我们需要一个中间人(app.vue),app.vue 将自己的实例 provide 出去

sister.vue:

export default {
    name:'sister',
    inject:['app'],
    data () {
        return {
           val:'我是sister的值'
        };
    },
    methods:{
        emit(){
            //注册自定义事件
            this.app.$emit('custom-event',this.val)
        }
    }
}

brotherChild.vue:

export default {
    name:'brotherChild',
    inject:['app'],
    data () {
        return {
           
        };
    },
    //在实例创建后监听自定义事件
    created(){
        this.app.$on('custom-event',function(msg){
            console.log(msg)//输出结果 我是来自sister的值
        })
    }
}

想了想,这个方法也可以适用于上面的所有场景,用app.vue作为中间人,子组件在父组件上注册自定义事件,又通过父组件来监听事件拿到值。

 

如果不想用app.vue作为中间人的话,也可以在,main.js中新建一个vue实例,export出去

export const eventBus = new Vue()

 

import {eventBus} from 'main.js'
export default {
    name:'sister',
    data () {
        return {
           val:'我是sister的值'
        };
    },
    methods:{
        emit(){
            //注册自定义事件
            eventBus.$emit('custom-event',this.val)
        }
    }
}
import {eventBus} from 'main.js'
export default {
    name:'brotherChild',
    data () {
        return {
           
        };
    },
    //在实例创建后监听自定义事件
    created(){
        eventBus.$on('custom-event',function(msg){
            console.log(msg)//输出结果 我是来自sister的值
        })
    }
}

但是这种方法用多了也会出现一个问题,就是数据的流向不明确,比如谁定义了这个事件,谁又监听了这个事件,都没有一个明确的标识,维护起来也比较困难。其实也能够通过对事件命名来缓解这个问题,不过始终还是不优雅。

emmmmm...貌似还是vuex好用点,哈哈哈哈。

这些方法也见仁见智吧,具体情况具体分析,选用合适的方法才是最佳方案!

你可能感兴趣的:(vue)