vue组件插槽

2023-12-13 10:49:48

组件的插槽

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

普通插槽

组件本身是一个容器,这个容器本身是空的,当我们把需要封装的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>

<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个出现在标题的下方

<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,但是,从效果上来看只是单纯把插入的内容复制了一份,分别插入不同的插槽里面

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

<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属性可以设置的,如果设置一些其他的值,我们就把这个插槽叫做具名插槽

<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标签也会出现在下面的插槽里面

插槽作用域

<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”

<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>

插槽作用域旧版本语法

<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>

新版本语法

<one>
    <template v-slot:footer="scope">
        <p>{{scope.userName}}</p>
        <p>{{scope.age}}</p>
    </template>            
</one>

最新语法

<one>
    <template #footer="{userName,age}">
        <p>{{userName}}</p>"
        <p>{{age}}</p>
    </template>            
</one>

代码分析:

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

文章来源:https://blog.csdn.net/qq_64558518/article/details/134902105
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。