zoukankan      html  css  js  c++  java
  • vue组件传值(8种方法)----props、$emit()、手动封装事件订阅observer、事件总线(Eventbus)、vuex、亲兄弟传值、provide/inject、插槽作用域

     

        1、父传子

            传递:当子组件中在父组件中当做标签使用的时候,给子组件绑定一个自定义属性,值为需要传递的数据
            接收:在子组件内部通过props进行接收,props接收的方式有2种:
                ①通过数组进行接收   props:["属性"]
                ②通过对象进行接收    props:{
                                        属性:{
                                            (1)type:限制数据的类型
                                            (2)default:默认值
                                            (3)required:布尔值,和default二选一
                                        }
                                    }
            步骤:
                ①在父组件中给子组件标签上添加自定义属性:
                    <son :custom="100"></son>
                ②子组件中通过props接收:
                    props:["custom"]
                ③接收到的custom可以直接在标签中使用 {{custom}}
            注意:今后只要看到props就要想到这个属性是用来接收外部数据的。

        2、子传父

            ①接收:当子组件在父组件中当做标签使用的时候,给当前子组件绑定一个自定义事件,值为需要接收值的函数,这个函数不允许加 ()
            ②传递的过程:在子组件内部通过this.$emit("自定义事件名称",需要传递的参数)来进行数据的传递
            步骤:
                ①父组件中给需要接收参数的子组件绑定自定义事件,值为需要接收值的函数:
                    <son @handler="handlerMsg"></son>
                    methods:{
                        handlerMsg(value){
                            console.log(value)// 这个值是通过this.$emit()触发传来的
                        }
                    }
                ②子组件中触发自定义事件:
                    this.$emit("handler",100);

        3、非父子传递

            第一种方法:通过给vue原型上添加一个公共的vue实例对象(vue实例对象上有$on()和$emit()),需要传递的一方调用$emit(),需要接收的一方调用$on()。

            步骤:
                ①main.js中:
                    Vue.prototype.$observer=new Vue();
                ②需要传递的组件中:
                    this.$observer.$emit("handler",100);
                ③需要接收的组件中:
                    this.$observer.$on("handler",(value)=>{
                        console.log(value)
                    });
                    注意:在挂载前(created)进行$on()绑定,先绑定好,再触发。

            *第二种方法:手动封装事件订阅observer

                步骤:
                    ①src下新建observer.js:
                        const eventList={};
    
                        const $on=function (eventName,callback) {  
                            if(!eventList[eventName]){
                                eventList[eventName]=[];
                            }
                            eventList[eventName].push(callback);
                        }
    
                        const $emit=function(eventName,params){
                            if(eventList[eventName]){
                                let arr=eventList[eventName];
                                arr.forEach((cb)=>{
                                    cb(params);
                                });
                            }
                        }
    
                        const $off=function(eventName,callback){
                            if(eventList[eventName]){
                                if(callback){
                                    let index=eventList[eventName].indexOf(callback);
                                    eventList[eventName].splice(index,1);
                                }else{
                                    eventList[eventName].length=0;
                                }
                            }
                        }
    
                        export default{
                            $on,
                            $emit,
                            $off
                        }
                    ②main.js中用手动封装的observer替代new Vue()
                        import observer from "./observer.js";
                        Vue.prototype.$observer=observer;
                    ③在需要传递的组件中用this.$observer.$emit()触发自定义事件:
                        this.$observer.$emit("customHandler","需要传递的值");
                    ④在需要接收的组件中用this.$observer.$on()绑定自定义事件:
                        this.$observer.$on("customHandler",this.toggle);





            第三种方法:事件总线(Eventbus)

                步骤:
                    ①先创建一个空实例:
                        let bus=new Vue();
                    ②通过bus.$on()绑定自定义事件:
                        bus.$on("customHandler",要触发的函数);
                    ③通过bus.$emit()来触发自定义事件: 
                        bus.$emit("customHandler");

            *第四种方法:vuex(后续)



            注:如果是亲兄弟:(父传子和子传父)

                步骤:
                    ①父组件中声明data数据 state:true ,将state通过props传给其中一个子组件:
                        <two :show="state"></two>
                        props:show
                        此时show的值随着state的变化而变化
                    ②再通过另一个子组件去改变父组件的state:
                        标签上绑定自定义事件:
                            <one @customHandler="toggle"></one>
                        再在子组件内部通过$emit()触发customHandler事件:
                            this.$emit("customHandler");



    provide / inject(提供/注入)跨组件传值,其实就是父传子


        provide / inject:依赖注入。可以实现跨组件传值,数据的流向只能是向下传递,就是大范围有效的props

        provide:这个配置项必须要在父级进行使用,用来定义后代组件所需要的一些属性和方法。
            语法:
                provide:{

                }
                // 推荐
                provide(){
                    return{
    
                    }
                }
        inject:这个配置项必须在后代组件中使用,用来获取根组件定义的跨组件传值的数据。
            语法:
                inject:[] 

                // 推荐
                inject:{
                    key:{
                        from:"父组件名称",
                        default:默认值
                    }
                }

    插槽 slot

        作用:默认情况下组件内部包裹的内容是不会显示的,如果需要进行显示则需要通过插槽来进行显示。

        1、匿名插槽:没有名字的插槽(v-slot:default)

            v-slot
            在组件内部通过<slot></slot>进行接收

            步骤:
                ①App.vue中在组件标签中添加template标签(里面可以写多个标签),写上v-slot属性
                    <Header>
                        <template v-slot>
                            <p>111</p>
                            <p>222</p>
                        </template>
                    </Header>
                ②在Header.vue组件中通过<slot></slot>开辟一块空间:
                    <div class="header">
                        <slot></slot>
                    </div>
        

        2、命名插槽:有名字的插槽

            v-slot:slotName
            在组件内部通过<slot name="slotName"></slot>来进行接收

            步骤:
                ①给插槽指令加上名字:
                    <template v-slot:slotName>
                        <p>111</p>
                    </template>
                ②slot标签添加name属性:
                    <div class="header">
                        <slot name="slotName"></slot>
                    </div>

                如果还有匿名插槽template,就在Header.vue中用<slot></slot>再开辟一块空间接收匿名插槽。
        

        3、插槽作用域:(子传父)

            v-slot:slotName(名字可写可不写,如果不写默认是default)="变量(这个变量是一个对象)"

            作用:让组件来提供自身需要显示的内容

            步骤:
                ①App.vue中template中设置v-slot="props"(props是一个对象):---------父
                    <template v-slot="props">
                        <h2>{{props.info}}</h2>
                    </template>
                ②Header.vue中slot标签绑定自定义属性info:----------子,info属性的值提供给父组件中的props.info
                    <div class="header">
                        <slot :info="'111'"></slot>
                    </div>
                ③在template中可以通过props.info拿到子组件中传来的值
     
                如果要用命名插槽:
                    App.vue:直接在v-slot后面加上 :slotName
                    Header.vue:<slot name="slotName" :info="'111'"></slot>

















  • 相关阅读:
    Android拍照+方形剪裁——附代码与效果图
    Caffe源代码中Solver文件分析
    Java学习笔记五(多线程)
    setTimeout和setInterval的区别
    javascript中this的妙用
    javascript基于原型的语言的特点
    css样式小技巧
    html块元素和内联元素
    怎么解决浏览器兼容性问题
    高效率、简洁、CSS代码优化原则
  • 原文地址:https://www.cnblogs.com/wuqilang/p/12341150.html
Copyright © 2011-2022 走看看