vue 组件之间的数据传递方法

几种方式:

  • props emit
  • provide inject (依赖注入)
  • this.$root     this.$parent    this.$refs(节点访问)
  • eventbus 事件触发器

1、props emit

这种传值分为两种方式,父组件→子组件; 子组件→父组件; (🧔👱‍♂️:和我们两个有关系嗷)

💢💥这种方式的缺点:如果组件嵌套层次多的话,数据传递比较繁琐

props 为父组件向子组件传递,emit事件则是子组件向父组件传递👇
传递描述

父🧔→子👱‍♂️

父组件给子组件传递值通过props。根节点vm>compa>compb

<div id="app">
    <compa :myname="name">
    <!--接收根节点的值-->
</div>
<script>
	//子组件
    const compb = {
        props: ['hername'],//负责接收父组件的属性
        template: '<h1>{{hername}}</h1>',
    }
    
    //父组件
    const compa = {
        props: ['myname'],//这里父组件的props是用来接收根节点的值的
        template:
            `<div>
                <h1>{{myname}}</h1>
                <compb :hername=myname></compb>
            </div>
            `,
        components: {
            compb
        }
    }
    var vm = new Vue({
        el: "#app",
        data: {
            name: "魅族牛逼"
        },
        components: {
            compa
        }
    })
</script>

具体传值看图👇得出props就是为了获得父组件的值。
传值图解
所以可以两个组件均可以打印出根节点的内容
打印

子👱‍♂️→父🧔

子组件通过emit发送事件,父组件通过v-on(@)来接收事件,再进行改变。
在子组件的文本框中输入文本,可以改变根节点的属性,并显示。

<div id="app">
    {{username}}
    <custom-input @ischange='handlerchange'></custom-input>
    <!--监听子组件的ischange事件 触发执行handlerchange回调函数-->
</div>
<script>
//子组件,文本框添加change事件,一旦文本内容被修改,则抛发 ischange 事件
    Vue.component('custom-input', {
        template:
            `
            <div>
                <input type="text"  @change="$emit('ischange',$event.target.value)"/>
            </div>
            `,
    })

    var vm = new Vue({
        el: "#app",
        data: {
            username: ''
        },
        methods: {
            handlerchange(val) {//事件处理函数,将data的值改为传来的值
                this.username = val;
            }
        }
    })
</script>

在文本框内输入则会在上方生成文本框内容,

父传子

换个写法(sync)✔

上面的 子👱‍♂️→父🧔 可以换个写法:
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。

这也是为什么推荐以 update:myPropName 的模式触发事件来取而代之。为了方便起见,我们为这种模式提供一个缩写,即 .sync修饰符:

  • 接收: @ischange='handlerchange':myusername.sync="username 直接跟属性名无需回调函数
  • 抛发:@change="$emit('ischange',$event.target.value)"@change="$emit('update:myusername',$event.target.value)"
<div id="app">
    {{username}}
    <custom-input-sync :myusername.sync="username"></custom-input-sync>
</div>
<script>
    Vue.component('custom-input-sync', {

        template:
            `
            <div>
                <input type="text"  @change="$emit('update:myusername',$event.target.value)"/>
            </div>
            `,
    })

    var vm = new Vue({
        el: "#app",
        data: {
            username: ''
        },
    })
</script>

2、provide inject (依赖注入)

官网讲解:看我的也可以,可以不用点我嗷亲😁

  • provide :写在祖先组件中,包含可注入其子孙的属性 provide:Object | () => Object
  • inject: 写在子孙组件中,用来接收祖先中传来的属性:inject:Array<string> | { [key: string]: string | Symbol | Object },后跟一个字符串数组或者一个对象。

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

👇该例子嵌套两层,并不影响使用,使用与嵌套层数无关

<div id="app">
    <compa :myname="name">
</div>
<script>
    const compb = {
        inject: ['username'],//接收provide的属性
        template: '<h1>!!!看看老子👉{{username}}</h1>',
    }
    const compa = {
        template:
            `<div>
                <compb></compb>
            </div>
            `,
        components: {
            compb
        }
    }


    var vm = new Vue({
        el: "#app",
        data: {
            name: "张三"
        },
        components: {
            compa
        },

        provide: function () {
            return {
                username: this.name//存放需要传递的属性
            }
        }
    })
</script>

轻松获得受气包——张三同志
在这里插入图片描述
💢💥这种方式的缺点:provide 和 inject 绑定并不是可响应的。

$root | $parent | $children | ref

  • $root : 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
  • $parent: 父实例,如果当前实例有的话
  • $children: 当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。
  • ref: 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
<div id="app">
    <input type="text" ref="father" :value="name">
    <!-- ref设为father,方便通过$refs.father来调用 -->
    <compa :myname="name">
</div>
<script>
    const compb = {
        template: '<h1>"看看老子"-{{$root.name}}</h1>',
        //可以直接通过$root来访问根节点name属性
        data() {
            return {
                title: "我是儿子的属性"
            }
        },
        mounted() {
            console.log("compb:" + this.$root.name)//compb:张三
            //获得根节点的name属性
            console.log("compb:" + this.$parent.title)//compb:我是爸爸的属性
            //获得父组件的title属性
            console.log("compb:" + this.$parent.starts())//compb:我是爸爸的方法
            //执行父组件的starts方法
        }
    }
    const compa = {
        props: ['myname'],
        template://下面子组件设置ref为son,方便通过$refs.son来调用
            `<div>
                <h1>{{myname}}</h1>
                <compb ref="son"></compb>
            </div>
            `,
        components: {
            compb
        },
        data() {
            return {
                title: "我是爸爸的属性"
            }
        },
        methods: {
            starts() {
                return '我是爸爸的方法'
            }
        },
        mounted() {
            console.log("compa:" + this.$refs.son.title)//compa:我是儿子的属性
            //父组件通过$refs.son访问dom获取title属性
            console.log("compa:" + this.$children[0].title)//compa:我是儿子的属性
            //父组件通过$children来获取子组件属性
        }
    }


    var vm = new Vue({
        el: "#app",
        data: {
            name: "张三"
        },
        components: {
            compa
        },
        mounted() {
            console.log("root:" + this.$refs.father.value)//root:张三
            //根节点通过$refs.father来访问dom获取文本框的value值
        }
    })
</script>

在这里插入图片描述

3、Eventbus 🚌

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

💢💥这种方式的缺点:不支持响应式。

案例👇:点击按钮,将根节点的属性,传递到子组件的eventbus中,并打印

<div id="app">
    <compa>
        <button @click="handlerclick">send</button>
    </compa>
</div>
<script>
    var eventbus = new Vue();//定义eventbus

    const compb = {
        template: '<h1>compb</h1>',
        mounted() {
            eventbus.$on('message', function (msg) {
                //event.on用来监听
                console.log(msg);
            })
        }
    }
    const compa = {
        template:
            `<div>
                <slot></slot>
                <h1>compa</h1>
                <compb></compb>
            </div>
            `,
        components: {
            compb
        }
    }


    var vm = new Vue({
        el: "#app",
        data: {
            name: "xiaoxue"
        },
        components: {
            compa
        },
        methods: {
            handlerclick() {
                eventbus.$emit('message', '我是数据')
                //eventbus.$emit抛发事件
            }
        }
    })
</script>

在这里插入图片描述

最后

其实还有个vuex,那玩意也是可以用来组件之间传递数据的,而且很香,详细请移步:😈莫挨老子😈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值