zoukankan      html  css  js  c++  java
  • vue-day04----组件传值、provide/inject、插槽(slot)、动态组件、keep-alive、directive

    ### 组件传值

        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:
                    <div class="header">
                        <slot :info="'111'"></slot>
                    </div>
                ③在template中可以通过props.info拿到子组件中传来的值
                如果要用命名插槽:
                    App.vue:直接在v-slot后面加上 :slotName
                    Header.vue:<slot name="slotName" :info="'111'"></slot>



    `以上都是组件传值`



    ### 动态组件

        通过vue的内置组件components的is属性来动态的切换页面
        is的值是哪个组件就会显示哪个组件,一般is前面有冒号表示动态组件。
        步骤:
            ①在Mine.vue中,在组件配置项中添加name属性:
                export default{
                    name:Mine
                }
            ②App.vue中设置data属性,用一个变量componentName接收name:
                export default{
                    data(){
                        return{
                            componentName:"Mine"
                        }
                    }
                }
                然后在component标签中添加is属性为变量componentName,就会渲染Mine组件:
                <component :is="componentName"></component>
        
      注意:component标签不显示在页面上
     
        场景:不在乎浏览器地址的时候可以用动态组件,如选项卡

    ### keep-alive

        keep-alive是vue的内置组件,用来包裹动态切换到路由或者组件,可以防止组件频繁的进行创建和销毁,从而达到性能优化的效果,当组件被keep-alive包裹的时候会增加两个生命周期:
            activated----活跃状态,进入的时候触发,可以进行数据请求
            deactivated----缓存状态,离开的时候触发
        使用:
            <keep-alive>
                <component :is="componentName"></component>
            </keep-alive>
            正常的组件显示会显示创建前、创建后、挂载前、挂载后4个生命周期。在切换时会经历当前组件的创建前、创建后、挂载前,上一个组件的销毁前和销毁后,再进行当前组件的挂载后,共6个生命周期。
            使用keep-alive包裹后,切换组件的时候,会直接经历当前组件的创建前、创建后、挂载前、挂载后,共4个生命周期,而省去了上一个组件的销毁前和销毁后。当所有的组件都经历了创建和挂载后,就全部储存在缓存里,之后进行的切换都是在缓存中拿数据。
            在当前组件mounted的前后分别是上一个组件的deactivated和当前组件的activated。deactivated和activated每次都会切换都会触发,所以数据请求放在activated中。
        属性:
            include----包括,需要被缓存的组件(字符串、正则)
            exclude----排除,不需要被缓存的组件(实时更新的组件)(字符串、正则)
            max----最多能被缓存多少个组件,项目中组件特别多的时候即使用了include也会造成缓存压力,就用max规定下最多可以缓存几个,超过该值后面的会将前面的替代掉,会重新走一遍生命周期流程(Number)
        注意:
            1、include和exclude不能同时使用,如果使用正则,属性前加冒号
            2、实时更新的组件不要用keep-alive

    ### 自定义指令  directive

        全局自定义指令:Vue.directive()
        局部自定义指令:directives
        directive(参数一,参数二)
            参数一:指令名称
            参数二:指令的配置项,可以是函数,也可以是对象
                函数:
                    参数一:使用当前指令的元素
                    参数二:指令的详细信息
                        {
                            modifiers:修饰符(只要自定义指令后面跟了修饰符,modifiers对象中就有值,为true),
                            value:指令的值(假设指令这样写:<div v-test="'aaa'"></div>,那么value就是aaa)
                        }
                        
        
        指令的作用:操作DOM元素
        步骤:
            ①src下新建utils/utils.js:
                import Vue from "vue";
    
    
                /**
                *  v-test指令:
                *      <div v-test="'发发发'"></div>
                *      相当于
                *      <div>发发发</div>
                * 
                */
                Vue.directive("test",(el,{value})=>{
                    el.innerText=value;
                });
    
    
                /**
                *  设置背景颜色的指令 
                * 
                */
                Vue.directive("backgroundColor",(el,{value,...rest})=>{
                    el.style.backgroundColor=value;
                });
    
    
                /**
                *  阻止浏览器默认事件:v-event.prev
                * 
                */
                Vue.directive("event",(el,{modifiers})=>{
                    let {prev}=modifiers;
                    el.addEventListener("contextmenu",(e)=>{
                        if(prev){
                            e.preventDefault();
                        }
                    });
                });
                
                /**
                *  自动聚焦
                * 
                */
                Vue.directive("focus",{
                    inserted(el){
                        el.focus();
                    }
                });
            ②main.js中引入:
                import "./utils/utils.js";
            ③App.vue中使用自定义指令:
                <div v-test="'发发发'" v-backgroundColor.not="'blue'"></div>
                <div v-test="'阻止浏览器默认事件'" v-backgroundColor="'yellow'" v-event.prev></div>
                <input type="text" v-focus>









  • 相关阅读:
    西瓜书的读书笔记
    Tensorflow-gpu在windows10上的安装(anaconda)
    php 设置报错等级
    PHP 类型比较表
    PHP中的定界符格式
    php进制转换函数
    php魔法常量
    php中双$$与多$$
    php引用传值
    CSS3过渡效果实现菜单划出效果
  • 原文地址:https://www.cnblogs.com/wuqilang/p/12359535.html
Copyright © 2011-2022 走看看