插槽、组件通信、transition过渡、声明周期(四)

slot插槽

vue提供了一种将父组件的内容和子组件模板整合的方法,内容分发
如果想在组件内部添加内容的话,就在组件模板内部对应的位置添加slot标签,而且添加上name属性,指明与外部的标签相通,如果不写name属性的话,将外面所有未命名的标签添加到该位置上

<div id="app">
    <father>
        <p slot="zha">我叫渣渣辉</p>
    </father>
    <hr>
    <father></father>
    <hr>
    <father>
        <p slot="hi">他叫XXX</p>
        <p slot="she">她叫ZZZ</p>
        <p slot="you">你叫CCC</p>
    </father>
</div>
<template id="add">
    <div>
        <slot name="zha"></slot>
        <slot name="hi"></slot>
        <p>我叫Gordon-Liu</p>
        <slot name="hui"></slot>
        <slot name="she"></slot>
        <slot name="you"></slot>
    </div>
</template>
<script>
    Vue.component("father",{
        template:"#add"
    })
    new Vue({
        el:"#app"
    })
</script>
第二种方法:

v-slot必须在组件或template标签中使用,v-slot:p1就相当于上面的意思,给他后面附一个值,
先在组件内拿取属性的属性值,然后上面赋的值就可以用

<div id="app">
    <hello>
        <template v-slot:p1="info">我叫... {{info.msg}} / {{info.arr}}</template>
    </hello>
</div>

<template id="add">
    <div>
        <slot name="p1" :msg="msg" :arr="arr"></slot>
    </div>
</template>
<script>
    Vue.component("hello",{
        template:"#add",
        data(){
            return {
                msg:"qwe",
                arr:[1,2,3,4]
            }
        }
    })
    new Vue({
        el:"#app"
    })
</script>

组件之间通信方式

1、父子组件传值
props emit

<div id="app">
    <father></father>
</div>

<template id="father"> 
    <div>
        <p>这是父组件...{{Msg}}</p>
        <hr>
        <son :change="chan"></son>      
        <!-- 2、该方式也可以获取整个函数(不加括号) -->
    </div>
</template>
<template id="son">
    <div>
        <p>这是子组件...{{msg}}</p>
        <p><button @click="change(msg)">对父组件说的话</button></p>
        <!-- 4、最后点击调用此方法 -->
    </div>
</template>
<script>
    Vue.component("father",{
        template:"#father",
        data(){             
            return {
                Msg:""
            }
        },
        methods:{       //1、整一个方法,子组件的值改变的时候,父组件的内容也随着变动
            chan(val){
                this.Msg=val
            }
        }
    })
    Vue.component("son",{
        template:"#son",
        props:["change"],       //3、将其变为父组件方法内的函数
        data(){
            return{
                msg:"今天下雨"
            }
        }
    })
    new Vue({
        el:"#app"
    })
</script>

第二种方法:自定义事件和$emit必须一起使用

<div id="app">
    <father></father>
</div>
<template id="father">
    <div>
        <p>这是父组件....{{Msg}}</p>
        <hr>
        <!--@change自定义事件与下面的$emit同时用 -->
        <son @change="chan"></son>
    </div>
</template>
<template id="son">
    <div>
        <p>这是子组件...{{msg}}</p>
        <p><button @click="cha">对父组件说的话</button></p>
    </div>
</template>
<script>
    Vue.component("father",{
        template:"#father",
        data(){
            return{
                Msg:""
            }
        },
        methods:{
            chan(val){
                this.Msg=val
            }
        }
    })
    Vue.component("son",{
        template:"#son",
        data(){
            return {
                msg:"今天有雨"
            }
        },
        //$emit相当于导火索,调用此方法的话,就会触发该事件,
        // 将第二个参数的内容传到上面自定义事件中的函数
        methods:{
            cha(){
                this.$emit("change",this.msg)
            }
        }
    })

    new Vue({
        el:"#app"
    })
</script>

2、ref
this.$refs.child
可以直接在方法内调用此方法
ref

    <template id="father">
        <div>
            <button ref="btn" @click="che">get</button>
            <son ref="son"></son>
        </div>
    </template>
 Vue.component("father",{
        template:"#father",
        methods:{
            che(){
                this.$refs.son.msg = "aaa";
                this.$refs.btn.style.background = "skyblue"
            }
        }
    })

3、 事件总线
mounted生命周期中进行监听

<template id="father">
    <div>
        <p>我是爹</p>
        <p @click="chen">打儿子</p>     
        <!-- 4、点击该触发事件 -->
    </div>
</template>
<template id="son">
    <div>
        <p>我是儿子</p>
        <p v-show="crying">呜呜呜呜呜~~~</p>
    </div>
</template>
<script>
    let att = new Vue()     //1、声明一个新对象
    Vue.component("father",{
        template:"#father",
        methods:{
            chen(){
                att.$emit("hiter")      //3、与自定义事件连在一起
            }
        }
    })
    Vue.component("son",{
        template:"#son",
        data(){
            return {
                crying:false
            }
        },
        methods:{
            hit(){
                this.crying=true
            }
        },
        mounted(){      //2、在对象中添加自定义事件,第二个参数是用方法中的函数
            att.$on("hiter",this.hit)
        }
    })
    new Vue({
        el:"#app"
    })
</script>

4、属性验证
props:{name:Number} 可以设置数据类型限制
Number,String,Boolean,Array,Object,Function,null(不限制类型)

拓展:
v-once 用在组件上有什么用?
v-once直接放在标签内用,且只能用一次,用完就失效
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>

<!-- 有子元素 -->
<div v-once>
  <h1>comment</h1>
  <p>{{msg}}</p>
</div>

<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>

<!-- `v-for` 指令-->
<ul>
  <li v-for="i in list" v-once>{{i}}</li>
</ul>

transition过渡:

transition多个元素过渡:
用transition-group的时候,外面都会自带一个span标签,所以必须要加个tag=“div”,将外面自带的标签变为div,name属性是与上面的样式相对应,key值是必须加:是虚拟dom原理,给每一个元素都加上唯一的值

<transition-group tag="div" name="a">
            <p v-show="show" key="1">Gordon-Liu</p>
            <p v-show="show" key="2">Gordon-Liu</p>
            <p v-show="show" key="3">Gordon-Liu</p>
            <p v-show="show" key="4">Gordon-Liu</p>
        </transition-group>
<style>
    p{
        width:200px;
        height:200px;
        background:skyblue;
        color:purple;
        font-size:20px;
        margin:50px;
        display:inline-block
    }
    .a-enter{
        transform:scale(1.5);
        opacity:0
    }
    .a-enter-to{
        transform:scale(1);
        opacity:1
    }
    .a-leave{
        transform:scale(1);
        opacity:1
    }
    .a-leave-to{
        transform:scale(1.5);
        opacity:0
    }
    .a-enter-active,.a-leave-active{
        transition:all 2s;
    }
</style>
<script>
    Vue.component("aaa",{
        template:"#aaa",
        data(){
            return{
                show:true
            }
        }
    })
    new Vue({
        el:"#app"
    })
</script>

结合css动画库
apper是初始化的意思,页面刚进入执行一次此效果

<div id="app">
    <button @click="type = type == 'aaa' ? 'bbb' : 'aaa'">toggle</button>
    <transition
        appear
        enter-active-class="animated zoomInDown"
        leave-active-class="animated zoomOutDown"
        mode="out-in"
    >
        <component :is="type"></component>
    </transition>
</div>
<script>
// in-out:新元素先进行过渡,完成之后当前元素过渡离开。
// out-in:当前元素先进行过渡,完成之后新元素过渡进入。
     new Vue({
         el:"#app",
         data:{
             type:"aaa"
         },
         components:{
             "aaa":{
                 template:"<h1>AAAAAAAAAAAAA</h1>"
             },
             "bbb":{
                 template:"<h1>BBBBBBBBBBBBBB</h1>"
             }
         }
     })
</script>

生命周期

<div id="app"> 
    <my-component></my-component>
</div>

<!--定义组件的模板-->
<template id="my-component">
    <div>
        <h1 id="title">我是h1 -- {{msg}}</h1>    
        <input type="text" v-model="msg">
        <button @click="destroy">销毁组件</button>
    </div>
</template>
   <script>
        /*
            组件从创建到销毁的一系列过程叫做组件的声明周期。
            vue在整个生命周期里面提供了一些函数,可以在内部实现一些业务逻辑,
            并且这些函数会在一些特定的场合下去执行。(在生命周期的某一个时刻进行触发)
            
            组件的生命周期大体可以分为三个阶段: 初始化、运行中、销毁
            初始化阶段:beforeCreate created beforeMount (render) mounted
            运行中阶段:beforeUpdate updated
            销毁阶段:  beforeDestroy destroyed
        */
        //初始化阶段
        //1.一个组件或者实例的生命周期都是从new开始的
        //2.实例化之后,内部会做一些初始化的事件与生命周期相关的配置
        Vue.component("my-component",{
            template:"#my-component",
            data(){
                return {
                    msg:"hello"
                }
            },
            methods:{
                destroy(){
                    this.$destroy() //组件销毁方法
                }
            },
            //3.beforeCreate这个钩子函数初始化的时候就会执行
            //但是数据是获取不到的,并且真实dom元素也是没有渲染出来的
            beforeCreate(){
                console.log("beforeCreate...")
                console.log(this.msg,document.getElementById("title"))
            },
            //4.created钩子函数内部可以访问到数据了,但是页面当中真实dom节点还是没有渲染出来
            //在这个钩子函数里面,可以进行相关初始化事件的绑定、发送ajax操作
            //当组件还没有挂载完毕之前,更改数据的话,是不会触发运行时钩子函数的执行!
            created(){
                console.log("created...")
                this.timer = setInterval(()=>{
                    console.log("定时器开着哦...")
                    this.msg = this.msg+"!"
                },2000)
                // this.msg = 11111111111
                console.log(this.msg,document.getElementById("title"))
            },
            //5.接下来的过程,就是组件或者实例去查找各自的模板结构,然后将其编译成虚拟dom
            //6.beforeMount代表dom马上就要被渲染出来了,但是却还没有真正的渲染出来
            //这个钩子函数与created钩子函数用法基本一致,可以进行相关初始化事件的绑定、发送ajax操作
            beforeMount(){
                console.log("beforeMount...")
                console.log(this.msg,document.getElementById("title"))
            },
            //生成好虚拟dom,然后内部通过render函数将对应的el进行替换,做一个初始化的虚拟dom渲染真实dom过程
            // render(){
            //     console.log("render....")
            // }
            //7.mounted钩子函数是挂载阶段的最后一个钩子函数
            //数据挂载完毕,真实dom元素也已经渲染完成了
            //这个钩子函数内部可以做一些实例化相关的操作   拖拽
            mounted(){
                console.log("mounted...")
                console.log(this.msg,document.getElementById("title"))
            },
            //8.这个钩子函数初始化的不会执行
            //当组件挂载完毕的时候,并且当数据改变的时候,才会立马执行
            //这个钩子函数获取dom的内容是更新之前的内容
            beforeUpdate(){
                console.log("beforeUpdate...",this.msg ,document.getElementById("title").innerHTML)
            },
            //9.这个钩子函数获取dom的内容是更新之后的内容
            //生成新的虚拟dom,新的虚拟dom与之前的虚拟dom进行比对,差异之后,就会进行真实dom渲染。
            //在updated钩子函数里面就可以获取到因diff算法比较差异得出来的真实dom渲染了。
            updated(){
                console.log("updated....", this.msg,document.getElementById("title").innerHTML)
            },
            //10.当组件销毁的时候,就会触发
            //这个钩子函数代表销毁之前,可以做一些善后操作
            //可以清除一些初始化事件、定时器相关的东西。
            beforeDestroy(){
                console.log("beforeDestory....")
                clearInterval(this.timer)
            },
            //11.组件销毁的时候执行
            //watch/数据劫持等功能已经完全丧失 
            destroyed(){
                console.log("destroyed...")
            }
        })
        new Vue().$mount("#app");
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值