vue从入门到放弃——(8) 组件高级(父子组件和solt槽口)

本文深入探讨Vue.js中父子组件间的通信机制,包括组件作用域独立性、基本调用方式、正向与逆向传值技巧,以及如何利用slot实现内容插槽的灵活运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

组件高级

父子组件

语法:

components:{
	‘parent’: {
		template:<div></div>,
		components:{
			‘child’: {
				template:<div></div>}
		}
	}
}
父子组件的作用域

1.组件相当于完整的vue实例
2.组件与vue实例间作用域独立(组件与vue实例中data数据不互通)
3.父子组件间作用域相互独立

子组件的调用

子组件只能在父组件的模板(template)中进行调用

[外链图片转存失败(img-YHl5Zex6-1562157343966)(…/AppData/Roaming/Typora/typora-user-images/1561721699629.png)]

基本的父子组件

eg:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div class="box">
        <fu></fu>
    </div>


    <template id="fuDiv">
        <div>
            <p>{{fText}}</p>
            <zi></zi>
        </div>
    </template>
    <template id="ziDiv">
        <div>
            <p>{{zText}}</p>
        </div>
    </template>
</body>

</html>
<script src="./node_modules/vue/dist/vue.min.js"></script>
<script>
    new Vue({
        el: ".box",
        data: {},
        components: {
            "fu": {
                template: "#fuDiv",
                data() {
                    return {
                        "fText": "我是父数据"
                    }
                },
                components: {
                    "zi": {
                        template: "#ziDiv",
                        data() {
                            return {
                                "zText": "我是子数据"
                            }
                        }
                    }
                }
            }
        }
    })
</script>
现在的组件ex其实可以用父组件和子组件来完成
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .big {
            position: fixed;
            bottom: 0;
            width: 100%;
            border-top: 1px solid red;
            height: 100px;
        }

        .small {
            width: 20%;
            float: left;
            text-align: center;
        }
    </style>
</head>

<body>
    <div class="box">
        <father></father>
    </div>
    <template id="fTem">
        <div>
            <div class="big">
                <son v-for="(v,i) in arr" :img-url="v.img" :title="v.title"></son>
            </div>
        </div>
    </template>
    <template id="sTem">
        <div class="small">
            ![在这里插入图片描述]()
            <p>{{title}}</p>
        </div>
    </template>
</body>

</html>
<script src=" ./node_modules/vue/dist/vue.min.js"> </script>
<script>

    new Vue({
        el: ".box",
        data: {},
        components: {
            "father": {
                template: "#fTem",
                data() {
                    return {
                        arr: [
                            { "img": "./img/1.png", "title": "首页" },
                            { "img": "./img/2.png", "title": "首页" },
                            { "img": "./img/3.png", "title": "首页" },
                            { "img": "./img/4.png", "title": "首页" },
                            { "img": "./img/5.png", "title": "首页" }
                        ]
                    }
                },
                components: {
                    "son": {
                        template: "#sTem",
                        props: {
                            "title": String,
                            "imgUrl": String
                        }
                    }
                }
            }
        }
    })
</script>
父子组件中传值

1.父子组件间作用域相互独立所以没有办法直接调用,必须借助于自定义事件来进行传值
2.子组件传值给父组件叫逆向传值(是不允许的 必须要有事件触发才能传值)
3.父组件传值给子组件叫正向传值(不需要事件触发)

正向传值
props 选项

props选项用来声明它期待获得的数据props 本质:props 为元素属性

props 的声明

语法:如果是驼峰命名法需要把大写转小写前面加-
JS 中:
props:[‘message1’, ‘messAge2’…]
HTML 中:
<组件 message=‘val’mess-age2=‘val’></组件>

props 的使用

与 data 一样,props 可以用在模板中
可以在 vm 实例中像 this.message 这样使用

props 验证

我们可以为组件的 prop 指定验证要求,例如知道的这些数据的类型。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="demodiv">
        <fu></fu>
    </div>
    <template id="futem">
        <div>
            <p>fufufuf</p>
            <zi :zitext="futext" zinum="hahah"></zi>
        </div>
    </template>

    <template id="zitem">
        <div>
            <p>{{zitext}}</p>
            <p>{{zinum}}</p>
        </div>
    </template>

</body>

</html>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    new Vue({
        el: "#demodiv",
        data: {},
        components: {
            "fu": {
                template: "#futem",
                data() {
                    return {
                        futext: 1
                    }
                },
                components: {
                    "zi": {
                        template: "#zitem",
                        // props验证来完成props的定义
                        props: {
                            zitext: Number,
                            zinum: {
                                type: String,
                                default: "我是默认值"
                            }
                        }

                    }
                }
            }
        }

    })
</script>
注意:在进行props验证时为什么写的没有错但是没有错误提示?

生产版本也就是压缩版的文件删除了警告,所以使用非压缩版的js文件就可以看到错误

逆向传值

逆向传值就是子组件给父组件传递数据,那么在这个时候默认是不允许,必须要用自定义事件来传递,要进行传递的时候还需要使用事件来进行触发。

  1. 逆向传值,需要通过时间来触发一个自定义事件的抛出操作
  2. 父组件接受子组件抛出的内容
抛出自定义事件监 听

要传值必须要先抛出,在接收

语法:

this. e m i t ( ‘ e v e n t ’ , v a l ) = = = = emit(‘event’,val)== == emit(event,val)====emit:实例方法,用来触发事件监听

接收自定义事件监听
语法:

<component @抛出的事件名=‘函数不加()不加()’>
fn:function(val){
}

val:自定义事件传递出的值

事件触发及接收原则:
谁触发的监听,由谁接收监听

eg:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div class="box">
        <fu></fu>
    </div>

    <template id="futem">
        <div>
            <p>我是父元素-------{{futext}}</p>
            <zi @zipao="fufun"></zi>
        </div>
    </template>
    <template id="zitem">
        <div>
            <p @click="zifun()">我是子元素-------{{zitext}}</p>
        </div>
    </template>
</body>

</html>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    new Vue({
        el: ".box",
        data: {},
        components: {
            "fu": {
                template: "#futem",
                data() {
                    return {
                        "futext": "我是父组件的数据",
                    }
                },
                methods:{
                    fufun(val){
                        this.futext=val;
                    }
                },
                components: {
                    "zi": {
                        template: "#zitem",
                        data() {
                            return {
                                "zitext": "我是子组件的数据",
                            }
                        },
                        methods:{
                            zifun(){
                                this.$emit("zipao",this.zitext)
                            }
                        }
                    }
                }
            }
        }
    })
</script>
slot槽口
作用:

用来混合父组件的内容与子组件自己的模板
内容不同数量也不同的时候使用

普通的槽口看起来更方便,但是不宜维护

语法:

声明组件模板:定义组件的时候留下slot等待调用的时候插入内容

[外链图片转存失败(img-nClKwrHq-1562157343968)(…/AppData/Roaming/Typora/typora-user-images/1561982611723.png)]

使用:

调用组件模板:调用的时候直接插入

[外链图片转存失败(img-ZhFNLV4Y-1562157343968)(…/AppData/Roaming/Typora/typora-user-images/1561982620184.png)]

eg:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div class="box">
        <fu>
            <!-- 调用的时候需要使用slot属性 -->
            <p slot="solta">哈哈哈</p>
        </fu>
    </div>

    <template id="futem">
        <div>
            <p>{{futext}}</p>
            <!-- 槽口只能有一个name属性,不能有其他的属性,这是规范 -->
            <!-- 如果需要使用属性的话可以把他包裹起来,对父元素添加属性 -->
            <slot name="solta"></slot>
        </div>
    </template>
</body>

</html>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
    new Vue({
        el: ".box",
        data: {},
        components: {
            "fu": {
                template: "#futem",
                data() {
                    return {
                        "futext":"我是父组件的数据",
                    }
                }
            }
        }
    })
</script>
具名 slot

1.slot> 元素可以用一个特殊属性 name 来配置如何分发内容
2.多个slot可以有不同的名字
3.具名slot将匹配内容片段中有对应slot特性的元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值