Vue5--自定义组件/父子组件/组件多级传递/插槽

自定义全局组件

  1. <template id="模板id">中定义模板
  2. 在Vue.component中注册模板(“模板名”, {
    template: “#模板id”
    });
  3. 在html中通过<模板名></模板名>使用模板
<body>
<div id="app">
    <tem></tem>
</div>
<template id="temp">
    <div>
        <p>这是一个模板</p>
        <p>这真的是一个模板</p>
    </div>
</template>
<script>
    Vue.component('tem',{
        template:'#temp'
    });
    let vue = new Vue({
        el:'#app',
        data:{

        }
    });
</script>

自定义局部组件

  1. <template id="模板id">中定义模板
  2. 在Vue实例的components中以{}注册组件,注册形式为{ '模板名':{ template:'#模板id'}}
  3. 在该Vue实例绑定的标签中以 模板名 的形式使用组件
<body>
<div id="app">
    <tem></tem>
</div>
<template id="temp">
    <div>
        <p>这是一个模板</p>
        <p>这真的是一个模板</p>
    </div>
</template>
<script>
    let vue = new Vue({
        el:'#app',
        data:{

        },
        components:{
            'tem':{
                template:'#temp'
            }
        }
    });
</script>
</body>

自定义组件中的data和methods

  1. 自定义组件中的函数定义在methods中
  2. 自定义组件中的data定义在函数的返回值中
<body>
<div id="app">
    <tem></tem>
</div>
<template id="temp">
    <div>
        <p>{{msg}}</p>
        <button v-on:click="func">按钮</button>
    </div>
</template>
<script>
    Vue.component('tem',{
        template:'#temp',
        data:function(){
            return{
                msg:'这真的是一个模板'
            }
        },
        methods:{
            func(){
                console.log('我是一个自定义模板')
            }
        }
    })
    let vue = new Vue({
        el:'#app',
        data:{
        }
    });
</script>
</body>

使用keep-alive实现动态组件(组件是否显示)

在component中,根据is的值决定哪个组件被渲染
keep-alive能保存被隐藏的组件在隐藏之前的状态
所以通过 keep-alive 和 component 配合使用,能实现组件动态显示,并保存组件在隐藏之前的状态

<body>
<div id="app">
    <button @click="toggle">切换</button>
    <keep-alive>
        <component v-bind:is="name"></component>
    </keep-alive>
</div>
<template id="temp1">
    <p>{{msg}}</p>
</template>
<template id="temp2">
    <p>{{msg2}}</p>
</template>
<script>
    Vue.component('tem',{
        template:'#temp1',
        data:function(){
            return{
                msg:'这真的是一个模板'
            }
        },
        methods:{
            func(){
                console.log('我是一个自定义模板')
            }
        }
    });
    Vue.component('tem2',{
        template: '#temp2',
        data:function(){
            return{
                msg2:'我真的是一个模板吗'
            }
        }
    });
    let vue = new Vue({
        el:'#app',
        data:{
            name:'tem'
        },
        methods:{
            toggle(){
                this.name = this.name === 'tem'? 'tem2':'tem'
            }
        }
    });
</script>
</body>

组件中使用过渡动画

如果是单个组件就使用transition
如果是多个组件就使用transition-group
在默认情况下,进入动画和离开动画同时执行,如果要指定动画的执行顺序,在transition中指定mode

父子组件

通过在自定义组件中再定义其子组件的形式定义父子组件

<body>
<div id="app">
    <dadtemp></dadtemp>
</div>
<template id="dad">
    <div>
        <p>这是爸爸</p>
        <sontemp></sontemp>
    </div>
</template>
<template id="son">
    <p>这是儿子</p>
</template>
<script>
    let vue = new Vue({
        el:'#app',
        data:{
        },
        components:{
            "dadtemp":{
                template:'#dad',
                components:{
                    'sontemp':{
                        template:'#son'
                    }
                }
            }
        }
    });
</script>
</body>

在这里插入图片描述

父子组件之间的数据传递

如果子组件想访问父组件中的数据,必须由父组件传递,子组件接收
在父组件中通过v-bind传递数据,传递格式 v-bind:自定义接收名称 = “要传递数据”
在子组件中通过props接收数据,接收格式 props: [“自定义接收名称”]

<body>
<div id="app">
    <dadtemp></dadtemp>
</div>
<template id="dad">
    <div>
        <p>这是爸爸</p>
        <sontemp v-bind:dadname="name" v-bind:dadsex="sex"></sontemp>
    </div>
</template>
<template id="son">
    <div>
        <p>这是儿子---{{dadname}}==={{dadsex}}</p>
    </div>
</template>
<script>
    let vue = new Vue({
        el:'#app',
        data:{
        },
        components:{
            "dadtemp":{
                template:'#dad',
                data:function(){
                    return{
                        name:'这是爸爸的名字',
                        sex:'这是爸爸的性别'
                    }
                },
                components:{
                    'sontemp':{
                        template:'#son',
                        props:["dadname","dadsex"]
                    }
                }
            }
        }
    });
</script>
</body>

在这里插入图片描述

父子组件之间的方法传递

想要在子组件中调用父组件中的方法:
在父组件中通过v-on传递方法:传递格式 v-on:自定义接收名称 = “要传递方法”
在子组件中自定义一个方法:在自定义方法中通过 this.$emit(‘自定义接收名称’)触发传递过来的方法

<body>
<div id="app">
    <dadtemp></dadtemp>
</div>
<template id="dad">
    <div>
        <button @click="func">爸爸的按钮</button>
        <sontemp @dadfunc="func"></sontemp>
    </div>
</template>
<template id="son">
    <div>
        <button @click="sonfunc">儿子的按钮</button>
    </div>
</template>
<script>
    let vue = new Vue({
        el:'#app',
        data:{
        },
        components:{
            "dadtemp":{
                template:'#dad',
                methods:{
                    func(){
                        console.log('这是爸爸的方法')
                    }
                },
                components:{
                    'sontemp':{
                        template:'#son',
                        methods:{
                            sonfunc(){
                                this.$emit('dadfunc')
                            }
                        }
                    }
                }
            }
        }
    });
</script>
</body>

在这里插入图片描述

子组件调用父组件方法时传递参数

this.$emit(需要调用的函数名称,传递的参数…)

<body>
<div id="app">
    <dadtemp></dadtemp>
</div>
<template id="dad">
    <div>
        <button @click="func('baba')">爸爸的按钮</button>
        <sontemp @dadfunc="func"></sontemp>
    </div>
</template>
<template id="son">
    <div>
        <button @click="sonfunc">儿子的按钮</button>
    </div>
</template>
<script>
    let vue = new Vue({
        el:'#app',
        data:{
        },
        components:{
            "dadtemp":{
                template:'#dad',
                methods:{
                    func(data){
                        console.log(data)
                    }
                },
                components:{
                    'sontemp':{
                        template:'#son',
                        methods:{
                            sonfunc(){
                                this.$emit('dadfunc','er')
                            }
                        }
                    }
                }
            }
        }
    });
</script>
</body>

在这里插入图片描述

组件命名

  1. 注册组件的时候使用了"驼峰命名", 那么在使用时需要转换成"短横线分隔命名"
    例如: 注册时: myFather -> 使用时: my-father
  2. 在传递参数的时候如果想使用"驼峰名称", 那么就必须写"短横线分隔命名"
    例如: 传递时: parent-name=“name” -> 接收时: props: [“parentName”]
  3. 在传递方法的时候不能使用"驼峰命名", 只能用"短横线分隔命名"
    @parent-say=“say” -> this.$emit(“parent-say”);
<div id="app">
    <my-father></my-father>
</div>
<template id="father">
    <div>
        <p>{{name}}</p>
        <button @click="say">我是按钮</button>
        <son :parent-name="name" @parent-say="say"></son>
    </div>
</template>
<template id="son">
    <div>
        <p>{{parentName}}</p>
        <button @click="sonFn">我是按钮</button>
    </div>
</template>
<script>
    // 父组件
    Vue.component("myFather", {
        template: "#father",
        data: function(){
            return {
                name: "lnj"
            }
        },
        methods: {
            say(){
                console.log("www.it666.com");
            }
        },
        // 子组件
        components: {
            "son": {
                template: "#son",
                props: ["parentName"],
                methods: {
                    sonFn(){
                        this.$emit("parent-say");
                    }
                }
            }
        }
    });
    // 这里就是MVVM中的View Model
    let vue = new Vue({
        el: '#app'
    });
</script>

组件多级传递

在Vue中如果儿子想使用爷爷的数据, 必须一层一层往下传递
在Vue中如果儿子想使用爷爷的方法, 必须一层一层往下传递

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入vue.js文件-->
    <script src="js/vue.js"></script>
    <style>
        *{
            margin:0;
            padding:0;
        }
    </style>
</head>
<body>
<div id="app">
   <yeyetemp></yeyetemp>
</div>
<template id="yeye">
    <div>
        <button @click="yeyefunc">爷爷的按钮</button>
        <p>{{msg}}</p>
        <dadtemp v-bind:yeyemsg="msg" @yefunc="yeyefunc"></dadtemp>
    </div>
</template>
<template id="dad">
    <div>
        <button @click="bafunc">爸爸的按钮</button>
        <p>{{yeyemsg}}</p>
        <sontemp v-bind:dadmsg="yeyemsg" @babafunc="bafunc"></sontemp>
    </div>
</template>
<template id="son">
    <div>
        <button @click="erfunc">儿子的按钮</button>
        <p>{{dadmsg}}</p>
    </div>
</template>
<script>
    Vue.component('yeyetemp',
        {
            template:'#yeye',
            data:function () {
                return{
                    msg:'我是你爷爷'
                }
            },
            methods:{
                yeyefunc(){
                    console.log('我是你爷爷');
                }
            },
            components:{
                'dadtemp':{
                    template:'#dad',
                    props:['yeyemsg'],
                    methods:{
                        bafunc(){
                            this.$emit('yefunc')
                        }

                    },
                    components:{
                        'sontemp':{
                            template:'#son',
                            props: ['dadmsg'],
                            methods:{
                                erfunc(){
                                    this.$emit('babafunc')
                                }
                            }
                        }
                    }
                }
            }
        })
    let vue = new Vue({
        el:'#app',
        data:{
        }
    });
</script>
</body>
</html>

在这里插入图片描述

匿名插槽

默认情况下,在父组件中调用子组件中,如果向子组件的标签中添加内容,则这部分内容不会被渲染。
使用slot插槽,在子组件中挖一个坑,父组件有需求时再填,实现动态添加子组件中的内容。
slot没有name属性时,是匿名插槽。在子组件中有几个匿名插槽,在父组件中填充的数据就会被拷贝几份,所以一般只写一个匿名插槽。

<body>
<div id="app">
    <temp>
        <div>这是将template中slot标签中的默认内容替换的数据</div>
    </temp>
</div>
<template id="tem">
    <div>
        <p>这是一个p</p>
        <slot>
            我是默认数据
        </slot>
        <p>这又是一个p</p>
    </div>
</template>
<script>
    Vue.component('temp',{
        template:'#tem'
    })
    let vue = new Vue({
        el:'#app',
        data:{
        }
    });
</script>
</body>

在这里插入图片描述

具名插槽

给slot添加name属性,就是具名插槽。在填充时,通过slot=‘插槽名’,将内容添加到该插槽中。没有给某具名插槽添加内容的,将会使用该插槽的默认内容。

<body>
<div id="app">
    <temp>
        <div slot="one">这是name=‘one'插槽的数据</div>
    </temp>
</div>
<template id="tem">
    <div>
        <p>这是一个p</p>
        <slot name="one">我是默认数据</slot>
        <slot name="two">我是默认数据</slot>
        <p>这又是一个p</p>
    </div>
</template>
<script>
    Vue.component('temp',{
        template:'#tem'
    })
    let vue = new Vue({
        el:'#app',
        data:{
        }
    });
</script>
</body>

在这里插入图片描述

v-slot

v-slot指令是Vue2.6中用于替代slot属性的一个指令
在Vue2.6之前, 我们通过slot属性告诉Vue当前内容填充到哪一个具名插槽
从Vue2.6开始, 我们通过v-slot指令告诉Vue当前内容填充到哪一个具名插槽

注意点: v-slot指令只能用在template标签上。可以使用#号替代v-slot

<body>
<div id="app">
    <temp>
            <template #one>
                <p>one中的内容</p>
            </template>
            <template #two>
                <p>two中的内容</p>
            </template>
    </temp>
</div>
<template id="tem">
    <div>
        <p>这是一个p</p>
        <slot name="one">我是默认数据</slot>
        <slot name="two">我是默认数据</slot>
        <p>这又是一个p</p>
    </div>
</template>
<script>
    Vue.component('temp',{
        template:'#tem'
    })
    let vue = new Vue({
        el:'#app',
        data:{
        }
    });
</script>
</body>

在这里插入图片描述

作用域插槽

作用域插槽就是带数据的插槽, 就是让父组件在填充子组件插槽内容时也能使用子组件的数据—》子组件提供数据, 父组件决定如何渲染

  1. 在slot中通过 v-bind:数据名="数据" 方式暴露数据
  2. 在父组件中通过 <template slot-scope="作用域名称"> 接收数据
  3. 在父组件的<template></template>中通过 作用域名称.数据名称 方式使用数据
  4. 匿名插槽可以使用#default="作用域" 具名插槽可使用#插槽名="作用域"
<body>
<div id="app">
    <temp>
            <template #default="obj">
                <li v-for="(name,index) in obj.names">{{name}}</li>
            </template>
            <template #one="obj2">
                <li v-for="(data,index) in obj2.datas">{{data}}</li>
            </template>
    </temp>
</div>
<template id="tem">
    <div>
        <p>ppppp</p>
        <slot :names="msg"></slot>
        <slot :datas="msg" name="one"></slot>
    </div>
</template>
<script>
    Vue.component('temp',{
        template:'#tem',
        data:function () {
            return{
                msg:["zs", "ls", "ww", "zl"]
            }
        }
    })
    let vue = new Vue({
        el:'#app',
        data:{
        }
    });
</script>
</body>
发布了119 篇原创文章 · 获赞 1 · 访问量 3949

猜你喜欢

转载自blog.csdn.net/weixin_42139212/article/details/103880555