vue组件插槽

组件的插槽

组件本身就是一个容器,也可以是一个vue对象,也是一个虚拟DOM

普通插槽

组件本身是一个容器,这个容器本身是空的,当我们把需要封装的html结构装进去之后,我们可以认为这个容器被塞满了,那就意味着,我们无法想组件内部添加新的html结构进去,但是我们想在每次调用组件的时候需要渲染一些个性化的东西,这个时候我们就需要给组件做一个预留空间,这个预留空间就是插槽

html 复制代码
<body>
    <div id="app">
        <one>
            <p>我是子标题</p>
        </one>
    </div>
    <template id="temp1">
        <div>
            <h2>我是标题</h2>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    let one = {
        template:"#temp1"
    }
    new Vue({
        el:"#app",
        components:{
            one
        }
    })
</script>

代码分析:

以上的代码渲染之后,我们在虚拟DOM中写入了一个p标签,着就是所谓的插入,但是并没有效果,因为我们并没有在one组件中预留空间,也就是插槽

如果想在组件内部预留插槽,使用 <slot></slot>

html 复制代码
<body>
    <div id="app">
        <one>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
        </one>
    </div>
    <template id="temp1">
        <div>
            <h2>我是标题</h2>
            <slot>
            	<!-- 组件内预留给插槽的空间 -->
            </slot>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    let one = {
        template:"#temp1"
    }
    new Vue({
        el:"#app",
        components:{
            one
        }
    })
</script>
一个插入点插入多个插槽

现在我们想让刚才的代码中前3个p标签出现在标题的上方,后面3个出现在标题的下方

html 复制代码
<body>
    <div id="app">
        <one>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
            <p>我是子标题</p>
        </one>
    </div>
    <template id="temp1">
        <div>
            <slot></slot>
            <h2>我是标题</h2>
            <slot></slot>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    let one = {
        template:"#temp1"
    }
    new Vue({
        el:"#app",
        components:{
            one
        }
    })
</script>

代码分析:

上面的代码中,我们发现,在模板中的标题上方也制作了一个插槽slot,但是,从效果上来看只是单纯把插入的内容复制了一份,分别插入不同的插槽里面

其实我们上面写的都是默认插槽,把插槽语法写完成如下

html 复制代码
<div id="app">
    <one>
        <p slot="default">我是子标题</p>
        <p slot="default">我是子标题</p>
        <p slot="default">我是子标题</p>
        <p slot="default">我是子标题</p>
        <p slot="default">我是子标题</p>
        <p slot="default">我是子标题</p>
    </one>
</div>
<template id="temp1">
    <div>
        <slot name="default"></slot>
        <h2>我是标题</h2>
        <slot name="default"></slot>
    </div>
</template>

默认情况下,所有的slot都必须要指定一个name,只是如果我们不自己指定的话,系统会给我们指定一个默认的名称default

具名插槽

在上面的插槽中,我们所有的slot如果在不指定name的情况下全都是default,但是这个name属性可以设置的,如果设置一些其他的值,我们就把这个插槽叫做具名插槽

html 复制代码
<div id="app">
    <one>
        <p slot="top">我是子标题</p>
        <p slot="top">我是子标题</p>
        <p slot="top">我是子标题</p>
        <p slot="bottom">我是子标题</p>
        <p slot="bottom">我是子标题</p>
        <p slot="bottom">我是子标题</p>
    </one>
</div>
<template id="temp1">
    <div>
        <slot name="top"></slot>
        <h2>我是标题</h2>
        <slot name="bottom"></slot>
    </div>
</template>

代码分析:

在上面的代码中,我们可以为插槽取一个名字,从而实现一对多,或者多对一的插入,当插槽有了名字之后,我们就可以在插入的时候指定插入到某一个插槽中

  • 我们组件里面定义插槽的时候使用slot标签,并且这个标签上面定义name属性,成为具名插槽
  • 在调用组件的时候,我们可以向指定的插槽插入内容,只需要在这个插入的元素上面添加一个slot="插槽名"即可
  • 具名插槽是可以多次使用的,所以我们可以把上面的top复制一份放到bottom的下面,这样上面三个p标签也会出现在下面的插槽里面

插槽作用域

html 复制代码
<body>
    <div id="app">
        <one>
            <p>我想要拿到组件内部的userName</p>
        </one>
    </div>
    <template id="temp1">
        <div>
            <h2>我是一个组件</h2>
            <slot>
                <!-- 组件的预留空间 -->
            </slot>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    let one = {
        template:"#temp1",
        data(){
            return {
                userName:"zhangsan"
            }
        }
    }
    new Vue({
        el:"#app",
        components:{
            one
        }
    })
</script>

之前我们一直都是外部的数据传递给内部,如果要把组件内部的数据传递给外部,我们可以:

1、利用对象的堆栈原理

2、自定义事件

注意:

我们现在要做一个区分,我们是可以把数据渲染在组件里面的,也可以渲染在插槽里面,但是这两种方式在向组件外部传值的时候是有区别的,我们上面说的这两种方法,只针对在组件内渲染的,如果是渲染在组件的插槽内部的,我们可以通过插槽作用域取拿

比如我们现在要userName的值传递到外面,我们可以在插入的标签上面添加一个slot-scope="scope"

html 复制代码
<body>
    <div id="app">
        <one>
            <div slot-scope="scope">
                <p>{{scope.userName}}</p>
                <p>{{scope.age}}</p>
            </div>            
        </one>
    </div>
    <template id="temp1">
        <div>
            <h2>我是一个组件</h2>
            <slot :user-name="userName" :age="18">
                <!-- 组件的预留空间 -->
            </slot>
        </div>
    </template>
</body>
<script src="js/vue.js"></script>
<script>
    let one = {
        template:"#temp1",
        data(){
            return {
                userName:"zhangsan"
            }
        }
    }
    new Vue({
        el:"#app",
        components:{
            one
        }
    })
</script>

插槽作用域旧版本语法

html 复制代码
<div id="app">
        <one>
            <div slot="footer" slot-scope="scope">
                <p>{{scope.userName}}</p>
                <p>{{scope.age}}</p>
            </div>            
        </one>
    </div>
    <template id="temp1">
        <div>
            <h2>我是一个组件</h2>
            <slot name="footer" :user-name="userName" :age="18">
                <!-- 组件的预留空间 -->
            </slot>
        </div>
    </template>

新版本语法

html 复制代码
<one>
    <template v-slot:footer="scope">
        <p>{{scope.userName}}</p>
        <p>{{scope.age}}</p>
    </template>            
</one>

最新语法

html 复制代码
<one>
    <template #footer="{userName,age}">
        <p>{{userName}}</p>"
        <p>{{age}}</p>
    </template>            
</one>

代码分析:

最新语法可以直接解构获取,并且v-slot这个指令也直接使用#来替代,简化代码

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax