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这个指令也直接使用#来替代,简化代码

相关推荐
小兵张健9 分钟前
开源 playwright-pool 会话池来了
前端·javascript·github
IT_陈寒3 小时前
Python开发者必知的5大性能陷阱:90%的人都踩过的坑!
前端·人工智能·后端
codingWhat4 小时前
介绍一个手势识别库——AlloyFinger
前端·javascript·vue.js
Lee川4 小时前
深度拆解:基于面向对象思维的“就地编辑”组件全模块解析
javascript·架构
代码老中医4 小时前
2026年CSS彻底疯了:这6个新特性让我删掉了三分之一JS代码
前端
进击的尘埃4 小时前
Web Worker 与 OffscreenCanvas:把主线程从重活里解放出来
javascript
不会敲代码14 小时前
Zustand:轻量级状态管理,从入门到实践
前端·typescript
踩着两条虫4 小时前
VTJ.PRO 双向代码转换原理揭秘
前端·vue.js·人工智能
扉川川4 小时前
OpenClaw 架构解析:一个生产级 AI Agent 是如何设计的
前端·人工智能
远山枫谷4 小时前
一文理清页面/组件通信与 Store 全局状态管理
前端·微信小程序